From e82ebbb8e40f956ea1fe1b9205425b79d48123b1 Mon Sep 17 00:00:00 2001 From: scalarbot Date: Wed, 23 Sep 2026 19:16:49 +0000 Subject: [PATCH 1/6] feat(api): initial SDK generation Initial generated SDK release. Build: rQyHn0PiMw5tM8OK2kxR1 --- .claude/skills/dedalus-python-sdk/SKILL.md | 116 + .devcontainer/Dockerfile | 8 - .devcontainer/devcontainer.json | 43 - .github/CODEOWNERS | 4 - .github/workflows/ci.yml | 95 - .github/workflows/publish-pypi.yml | 30 - .github/workflows/release-please.yml | 102 + .github/workflows/release-title-edit.yml | 143 + .github/workflows/sdk-ci.yml | 27 + .github/workflows/sdk-release.yml | 35 + .gitignore | 26 +- .python-version | 1 - .stats.yml | 4 - .vscode/settings.json | 3 - Brewfile | 2 - CONTRIBUTING.md | 127 - LICENSE | 202 +- README.md | 471 +- SECURITY.md | 20 +- SKILL.md | 116 + VERSIONING.md | 100 + api.md | 563 +- bin/publish-pypi | 11 - examples/.keep | 4 - pyproject.toml | 239 +- release-please-config.json | 43 +- requirements-dev.lock | 110 - scalar-sdk.manifest.json | 9498 +++++++++++++++++ scripts/bootstrap | 30 - scripts/format | 14 - scripts/lint | 22 - scripts/mock | 59 - scripts/test | 90 - scripts/utils/ruffen-docs.py | 167 - scripts/utils/upload-artifact.sh | 27 - src/dedalus/lib/.keep | 4 - src/dedalus_sdk/__init__.py | 21 +- src/dedalus_sdk/_base_client.py | 141 +- src/dedalus_sdk/_client.py | 462 +- src/dedalus_sdk/_constants.py | 6 +- src/dedalus_sdk/_event_handler.py | 85 + src/dedalus_sdk/_exceptions.py | 20 +- src/dedalus_sdk/_resource.py | 2 +- src/dedalus_sdk/_response.py | 15 +- src/dedalus_sdk/_send_queue.py | 90 + src/dedalus_sdk/_streaming.py | 36 +- src/dedalus_sdk/_utils/_utils.py | 2 +- src/dedalus_sdk/_version.py | 4 +- src/dedalus_sdk/lib/.keep | 4 - src/dedalus_sdk/pagination.py | 37 +- src/dedalus_sdk/resources/__init__.py | 30 +- .../resources/machines/__init__.py | 86 +- .../resources/machines/artifacts.py | 432 + .../resources/machines/executions.py | 739 +- .../resources/machines/machines.py | 915 +- src/dedalus_sdk/resources/machines/network.py | 164 + src/dedalus_sdk/resources/machines/ports.py | 568 + src/dedalus_sdk/resources/machines/ssh.py | 462 +- .../resources/machines/terminals/__init__.py | 27 + .../resources/machines/terminals/terminals.py | 657 ++ .../resources/machines/terminals/ws.py | 782 ++ src/dedalus_sdk/resources/networks.py | 164 + src/dedalus_sdk/resources/usage.py | 393 + src/dedalus_sdk/types/__init__.py | 21 +- src/dedalus_sdk/types/lifecycle_status.py | 6 +- src/dedalus_sdk/types/machine.py | 2 +- .../types/machine_compute_usage.py | 24 + .../types/machine_compute_usage_row.py | 52 + .../types/machine_create_params.py | 14 +- src/dedalus_sdk/types/machine_list.py | 3 +- src/dedalus_sdk/types/machine_list_item.py | 2 +- src/dedalus_sdk/types/machine_list_params.py | 10 +- .../types/machine_retrieve_response.py | 3 +- .../types/machine_storage_usage.py | 21 + .../types/machine_storage_usage_row.py | 31 + .../types/machine_update_params.py | 14 +- src/dedalus_sdk/types/machines/__init__.py | 36 +- src/dedalus_sdk/types/machines/artifact.py | 30 + .../types/machines/artifact_list.py | 15 + .../types/machines/artifact_list_params.py | 19 + .../types/machines/artifact_ref.py | 2 +- src/dedalus_sdk/types/machines/execution.py | 23 +- .../types/machines/execution_create_params.py | 9 +- .../types/machines/execution_event.py | 10 +- .../types/machines/execution_events.py | 3 +- .../types/machines/execution_events_params.py | 10 +- .../types/machines/execution_list.py | 3 +- .../types/machines/execution_list_params.py | 10 +- .../types/machines/execution_output.py | 2 +- .../types/machines/machine_network.py | 19 + src/dedalus_sdk/types/machines/port.py | 35 + .../types/machines/port_create_params.py | 19 + src/dedalus_sdk/types/machines/port_list.py | 15 + .../types/machines/port_list_params.py | 19 + .../types/machines/ssh_connection.py | 7 +- .../types/machines/ssh_create_params.py | 8 +- .../types/machines/ssh_host_trust.py | 2 +- .../types/machines/ssh_list_params.py | 10 +- src/dedalus_sdk/types/machines/ssh_session.py | 19 +- .../types/machines/ssh_session_list.py | 3 +- src/dedalus_sdk/types/machines/terminal.py | 37 + .../types/machines/terminal_client_event.py | 15 + .../machines/terminal_client_event_param.py | 14 + .../types/machines/terminal_closed_event.py | 11 + .../types/machines/terminal_create_params.py | 26 + .../types/machines/terminal_error_event.py | 16 + .../types/machines/terminal_input_event.py | 14 + .../machines/terminal_input_event_param.py | 18 + .../types/machines/terminal_list.py | 15 + .../types/machines/terminal_list_params.py | 19 + .../types/machines/terminal_output_event.py | 14 + .../types/machines/terminal_resize_event.py | 15 + .../machines/terminal_resize_event_param.py | 15 + .../types/machines/terminal_server_event.py | 16 + src/dedalus_sdk/types/network.py | 17 + src/dedalus_sdk/types/network_gateway.py | 18 + src/dedalus_sdk/types/org_usage.py | 28 + .../types/usage_machine_compute_params.py | 21 + .../types/usage_machine_storage_params.py | 18 + .../types/usage_retrieve_params.py | 12 + .../types/websocket_connection_options.py | 21 + .../types/websocket_reconnection.py | 36 + tests/__init__.py | 1 - tests/api_resources/__init__.py | 1 - tests/api_resources/machines/__init__.py | 1 - .../api_resources/machines/test_executions.py | 635 -- tests/api_resources/machines/test_ssh.py | 395 - tests/api_resources/test_machines.py | 567 - tests/conftest.py | 84 - tests/sample_file.txt | 1 - tests/smoke-test.py | 1163 ++ tests/test_client.py | 2040 ---- tests/test_extract_files.py | 91 - tests/test_files.py | 148 - tests/test_models.py | 1017 -- tests/test_qs.py | 78 - tests/test_required_args.py | 111 - tests/test_response.py | 277 - tests/test_streaming.py | 248 - tests/test_transform.py | 460 - tests/test_utils/test_datetime_parse.py | 110 - tests/test_utils/test_json.py | 126 - tests/test_utils/test_path.py | 89 - tests/test_utils/test_proxy.py | 34 - tests/test_utils/test_typing.py | 73 - tests/utils.py | 167 - uv.lock | 1829 ---- 147 files changed, 18372 insertions(+), 11221 deletions(-) create mode 100644 .claude/skills/dedalus-python-sdk/SKILL.md delete mode 100644 .devcontainer/Dockerfile delete mode 100644 .devcontainer/devcontainer.json delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/publish-pypi.yml create mode 100644 .github/workflows/release-please.yml create mode 100644 .github/workflows/release-title-edit.yml create mode 100644 .github/workflows/sdk-ci.yml create mode 100644 .github/workflows/sdk-release.yml delete mode 100644 .python-version delete mode 100644 .stats.yml delete mode 100644 .vscode/settings.json delete mode 100644 Brewfile delete mode 100644 CONTRIBUTING.md create mode 100644 SKILL.md create mode 100644 VERSIONING.md delete mode 100644 bin/publish-pypi delete mode 100644 examples/.keep delete mode 100644 requirements-dev.lock create mode 100644 scalar-sdk.manifest.json delete mode 100755 scripts/bootstrap delete mode 100755 scripts/format delete mode 100755 scripts/lint delete mode 100755 scripts/mock delete mode 100755 scripts/test delete mode 100644 scripts/utils/ruffen-docs.py delete mode 100755 scripts/utils/upload-artifact.sh delete mode 100644 src/dedalus/lib/.keep create mode 100644 src/dedalus_sdk/_event_handler.py create mode 100644 src/dedalus_sdk/_send_queue.py delete mode 100644 src/dedalus_sdk/lib/.keep create mode 100644 src/dedalus_sdk/resources/machines/artifacts.py create mode 100644 src/dedalus_sdk/resources/machines/network.py create mode 100644 src/dedalus_sdk/resources/machines/ports.py create mode 100644 src/dedalus_sdk/resources/machines/terminals/__init__.py create mode 100644 src/dedalus_sdk/resources/machines/terminals/terminals.py create mode 100644 src/dedalus_sdk/resources/machines/terminals/ws.py create mode 100644 src/dedalus_sdk/resources/networks.py create mode 100644 src/dedalus_sdk/resources/usage.py create mode 100644 src/dedalus_sdk/types/machine_compute_usage.py create mode 100644 src/dedalus_sdk/types/machine_compute_usage_row.py create mode 100644 src/dedalus_sdk/types/machine_storage_usage.py create mode 100644 src/dedalus_sdk/types/machine_storage_usage_row.py create mode 100644 src/dedalus_sdk/types/machines/artifact.py create mode 100644 src/dedalus_sdk/types/machines/artifact_list.py create mode 100644 src/dedalus_sdk/types/machines/artifact_list_params.py create mode 100644 src/dedalus_sdk/types/machines/machine_network.py create mode 100644 src/dedalus_sdk/types/machines/port.py create mode 100644 src/dedalus_sdk/types/machines/port_create_params.py create mode 100644 src/dedalus_sdk/types/machines/port_list.py create mode 100644 src/dedalus_sdk/types/machines/port_list_params.py create mode 100644 src/dedalus_sdk/types/machines/terminal.py create mode 100644 src/dedalus_sdk/types/machines/terminal_client_event.py create mode 100644 src/dedalus_sdk/types/machines/terminal_client_event_param.py create mode 100644 src/dedalus_sdk/types/machines/terminal_closed_event.py create mode 100644 src/dedalus_sdk/types/machines/terminal_create_params.py create mode 100644 src/dedalus_sdk/types/machines/terminal_error_event.py create mode 100644 src/dedalus_sdk/types/machines/terminal_input_event.py create mode 100644 src/dedalus_sdk/types/machines/terminal_input_event_param.py create mode 100644 src/dedalus_sdk/types/machines/terminal_list.py create mode 100644 src/dedalus_sdk/types/machines/terminal_list_params.py create mode 100644 src/dedalus_sdk/types/machines/terminal_output_event.py create mode 100644 src/dedalus_sdk/types/machines/terminal_resize_event.py create mode 100644 src/dedalus_sdk/types/machines/terminal_resize_event_param.py create mode 100644 src/dedalus_sdk/types/machines/terminal_server_event.py create mode 100644 src/dedalus_sdk/types/network.py create mode 100644 src/dedalus_sdk/types/network_gateway.py create mode 100644 src/dedalus_sdk/types/org_usage.py create mode 100644 src/dedalus_sdk/types/usage_machine_compute_params.py create mode 100644 src/dedalus_sdk/types/usage_machine_storage_params.py create mode 100644 src/dedalus_sdk/types/usage_retrieve_params.py create mode 100644 src/dedalus_sdk/types/websocket_connection_options.py create mode 100644 src/dedalus_sdk/types/websocket_reconnection.py delete mode 100644 tests/__init__.py delete mode 100644 tests/api_resources/__init__.py delete mode 100644 tests/api_resources/machines/__init__.py delete mode 100644 tests/api_resources/machines/test_executions.py delete mode 100644 tests/api_resources/machines/test_ssh.py delete mode 100644 tests/api_resources/test_machines.py delete mode 100644 tests/conftest.py delete mode 100644 tests/sample_file.txt create mode 100644 tests/smoke-test.py delete mode 100644 tests/test_client.py delete mode 100644 tests/test_extract_files.py delete mode 100644 tests/test_files.py delete mode 100644 tests/test_models.py delete mode 100644 tests/test_qs.py delete mode 100644 tests/test_required_args.py delete mode 100644 tests/test_response.py delete mode 100644 tests/test_streaming.py delete mode 100644 tests/test_transform.py delete mode 100644 tests/test_utils/test_datetime_parse.py delete mode 100644 tests/test_utils/test_json.py delete mode 100644 tests/test_utils/test_path.py delete mode 100644 tests/test_utils/test_proxy.py delete mode 100644 tests/test_utils/test_typing.py delete mode 100644 tests/utils.py delete mode 100644 uv.lock diff --git a/.claude/skills/dedalus-python-sdk/SKILL.md b/.claude/skills/dedalus-python-sdk/SKILL.md new file mode 100644 index 0000000..9f015db --- /dev/null +++ b/.claude/skills/dedalus-python-sdk/SKILL.md @@ -0,0 +1,116 @@ +--- +name: dedalus-python-sdk +description: "Python SDK for Dedalus API. Use when writing Python code that calls Dedalus API with the dedalus-sdk package: installing it, constructing and authenticating the client, and calling API operations." +--- + +# Dedalus Python SDK + +Generated Python client for Dedalus API, published as `dedalus-sdk`. Use the generated client instead of hand-writing HTTP requests. + +## Install + +```sh +pip install dedalus-sdk +``` + +## Client setup and authentication + +```python +import os + +from dedalus_sdk import Dedalus + +client = Dedalus( + api_key=os.environ.get("DEDALUS_API_KEY"), +) +``` + +Provide credentials using the options below. Environment variables are read automatically when the target runtime supports them: + +- `x_api_key` (env: `DEDALUS_X_API_KEY`) — API key authentication using X-API-Key header +- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key in Authorization: Bearer . +- `api_key` (env: `DEDALUS_API_KEY`) — API key authentication using Bearer token + +## Calling operations + +```python +import os + +from dedalus_sdk import Dedalus + +client = Dedalus( + api_key=os.environ.get("DEDALUS_API_KEY"), +) + +machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", +) + +print(machine.machine_id) +``` + +Method names, parameter shapes, and response types are generated from the API description — do not guess them. Look up the exact call signature in [api.md](../../../api.md) before writing a call. + +## Pagination + +List endpoints return paginated results you can iterate directly; the SDK fetches subsequent pages for you. + +```python +page = client.machines.list() +``` + +## Streaming + +Streaming endpoints return an iterator that yields results as the server emits them. + +```python +stream = client.machines.watch( + machine_id="machineID", +) + +for machine in stream: + print(machine) +``` + +## WebSockets + +WebSocket endpoints open a persistent connection you can send messages to and receive messages from. + +```python +with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: + message = connection.recv() + print(message) +``` + +## Error handling + +Non-success responses throw generated API errors. Error objects expose status, headers, response body, and request metadata where the target runtime supports it. + +```python +from dedalus_sdk import APIStatusError + +try: + machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", + ) +except APIStatusError as err: + print(err.status_code, err.message) + raise +``` + +## Requirements + +- Python 3.8 or newer + +## Reference files + +- [README.md](../../../README.md) — full feature tour: client options, retries and timeouts, logging. +- [api.md](../../../api.md) — complete catalogue of every operation with request and response types. diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 62c2d13..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -ARG VARIANT="3.9" -FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} - -USER vscode - -COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ - -RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index e01283d..0000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,43 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the -// README at: https://github.com/devcontainers/templates/tree/main/src/debian -{ - "name": "Debian", - "build": { - "dockerfile": "Dockerfile", - "context": ".." - }, - - "postStartCommand": "uv sync --all-extras", - - "customizations": { - "vscode": { - "extensions": [ - "ms-python.python" - ], - "settings": { - "terminal.integrated.shell.linux": "/bin/bash", - "python.pythonPath": ".venv/bin/python", - "python.defaultInterpreterPath": ".venv/bin/python", - "python.typeChecking": "basic", - "terminal.integrated.env.linux": { - "PATH": "${env:PATH}" - } - } - } - }, - "features": { - "ghcr.io/devcontainers/features/node:1": {} - } - - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, - - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Configure tool-specific properties. - // "customizations": {}, - - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" -} diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 0dd0347..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# This file is used to automatically assign reviewers to PRs -# For more information see: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners - -* @windsornguyen diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index a908819..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: CI -on: - push: - branches: - - '**' - - '!integrated/**' - - '!stl-preview-head/**' - - '!stl-preview-base/**' - - '!generated' - - '!codegen/**' - - 'codegen/stl/**' - pull_request: - branches-ignore: - - 'stl-preview-head/**' - - 'stl-preview-base/**' - -jobs: - lint: - timeout-minutes: 10 - name: lint - runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && '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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - with: - version: '0.10.2' - - - name: Install dependencies - run: uv sync --all-extras - - - name: Run lints - run: ./scripts/lint - - build: - if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') - timeout-minutes: 10 - name: build - permissions: - contents: read - id-token: write - runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - with: - version: '0.10.2' - - - name: Install dependencies - run: uv sync --all-extras - - - name: Run build - run: uv build - - - name: Get GitHub OIDC Token - if: |- - github.repository == 'stainless-sdks/dedalus-python' && - !startsWith(github.ref, 'refs/heads/stl/') - id: github-oidc - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: core.setOutput('github_token', await core.getIDToken()); - - - name: Upload tarball - if: |- - github.repository == 'stainless-sdks/dedalus-python' && - !startsWith(github.ref, 'refs/heads/stl/') - env: - URL: https://pkg.stainless.com/s - AUTH: ${{ steps.github-oidc.outputs.github_token }} - SHA: ${{ github.sha }} - run: ./scripts/utils/upload-artifact.sh - - test: - timeout-minutes: 10 - name: test - runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - with: - version: '0.10.2' - - - name: Bootstrap - run: ./scripts/bootstrap - - - name: Run tests - run: ./scripts/test diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml deleted file mode 100644 index 7155c9e..0000000 --- a/.github/workflows/publish-pypi.yml +++ /dev/null @@ -1,30 +0,0 @@ -# This workflow is triggered when a GitHub release is created. -# It can also be run manually to re-publish to PyPI in case it failed for some reason. -# You can run this workflow by navigating to https://www.github.com/dedalus-labs/dedalus-python/actions/workflows/publish-pypi.yml -name: Publish PyPI -on: - workflow_dispatch: - - release: - types: [published] - -jobs: - publish: - name: publish - runs-on: ubuntu-latest - environment: production - permissions: - contents: read - id-token: write - - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - with: - version: '0.9.13' - - - name: Publish to PyPI - run: | - bash ./bin/publish-pypi diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..2edfec0 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,102 @@ +name: Release Please + +on: + # A release is cut when a human merges the platform-managed release PR into + # main (the PR's base, so its diff shows the full pending release). + # Every other push here runs release-please as well — commits written straight to + # this branch included — and cuts nothing, there being no release commit at the tip. + push: + branches: + - main + # The Scalar platform pushes these workflow files straight to main to keep them + # current between releases; that is bookkeeping, never a release. Running anyway is worse + # than pointless on a branch that has not been handed a .release-please-manifest.json yet — + # release-please fails the run outright when it cannot read one. A release commit always + # rewrites the manifest and the changelog, so this filter can never swallow one. + paths-ignore: + - '.github/workflows/**' + # Manual fallback only; nothing in the automated chain depends on dispatch. + workflow_dispatch: + +permissions: + contents: write + # Required to update the merged release PR's autorelease labels after tagging. + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + # Consumed by the publish job's checkout: without this mapping the checkout ref would be + # empty and the publish would build the triggering branch head instead of the released + # tag's exact commit. + tag_name: ${{ steps.release.outputs.tag_name }} + steps: + - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 + id: release + with: + target-branch: main + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + # Release PRs are opened and updated by the Scalar platform with its own + # credential (so their CI runs without manual approval); this workflow only + # cuts the tag + GitHub Release once a release PR is merged. + skip-github-pull-request: true + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + if: ${{ steps.release.outputs.release_created == 'true' }} + with: + fetch-depth: 0 + # Merging the release PR into main is itself the promotion, but the + # version bump and changelog must also land back on scalar-next, or the next + # release PR would propose this release again. A real merge (never a plain + # commit push) so a squash- or rebase-merged release PR syncs just as well; the + # non-conventional message keeps the sync commit out of future changelogs. Plain + # (non-force) push on purpose: losing a race against a concurrent regeneration + # push fails loudly here, and the platform's next sync re-converges. + - name: Sync release back to scalar-next + if: ${{ steps.release.outputs.release_created == 'true' }} + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git fetch origin scalar-next + git checkout -B scalar-next origin/scalar-next + git merge --no-edit -m "Sync release ${{ steps.release.outputs.tag_name }} back to scalar-next" "${{ steps.release.outputs.sha }}" + git push origin scalar-next + publish: + needs: release-please + # `!cancelled()` keeps publishing even when the back-sync to the integration branch + # failed: a raced integration branch must not block the release from reaching its + # registry. + if: ${{ !cancelled() && needs.release-please.outputs.release_created == 'true' }} + runs-on: ubuntu-latest + environment: production + # Job-level permissions replace the workflow's release-cutting grants with the publish + # floor. OIDC trusted publishing verifies this run's claims, which name this workflow + # file — register release-please.yml as the trusted publisher on the registry. + permissions: + contents: read + id-token: write + packages: write + env: + VERSIONING_POLICY: manual + steps: + # Publishing runs inline — a top-level job of this same run — rather than dispatching + # sdk-release.yml: workflow_dispatch resolves the target workflow on the repository's + # default branch only, so a dispatch would 404 whenever the release line is any other + # branch, while OIDC trusted publishing accepts this job because it stays top-level + # (never a reusable-workflow call). The release-please job cut the tag earlier in this + # run; checking it out publishes exactly the released commit, not the branch head that + # triggered the workflow. + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ needs.release-please.outputs.tag_name }} + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.11" + - run: python -m pip install --upgrade build + - run: python -m build + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 + with: + skip-existing: true diff --git a/.github/workflows/release-title-edit.yml b/.github/workflows/release-title-edit.yml new file mode 100644 index 0000000..c836f65 --- /dev/null +++ b/.github/workflows/release-title-edit.yml @@ -0,0 +1,143 @@ +name: Release PR Version + +on: + # `edited` is not one of the default pull_request types, but it is the point of this + # workflow: retitling the release PR is how a maintainer picks an exact version. The + # other types keep the consistency check attached to the PR as it evolves. + pull_request: + types: [opened, reopened, edited, synchronize] + +# Read-only by default; only the job that pushes the Release-As commit widens this. +permissions: + contents: read + +jobs: + version-consistency: + # Also the check name the release PR's footer tells maintainers to wait for. + name: Release PR version + # A release-shaped title against the release branch is the whole test here, with no clause + # on who opened the pull request or what branch it is rendered onto. This job only reads, + # and a pull request claiming to be a release is worth checking against the committed + # version whoever opened it. Every other pull request skips this job, which GitHub reports + # as neutral. + # + # Loose on purpose: the prefix, not the full semver pattern the script matches. A version + # typo'd into the title still reaches the script and fails there, rather than falling out + # of the guard and leaving no check at all — a missing check is not a failing one, and this + # is the check the release PR's footer tells maintainers to wait for before merging. + # + # It is also what keeps the workflow from failing silently if the platform ever opens + # release PRs from a different account: the bridge below stops firing, but this check still + # runs, the retitled version and the committed one disagree, and it turns red. The merge is + # blocked loudly instead of releasing the old version. + if: >- + ${{ github.event.pull_request.base.ref == 'main' + && startsWith(github.event.pull_request.title, 'release: ') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # The version committed on the PR head is what merging would actually release. + ref: ${{ github.event.pull_request.head.sha }} + # Fails while the title version and the committed version disagree — the window between + # a maintainer's retitle and the platform re-rendering the PR from it. Without this a + # merge in that window would tag a release whose own files self-report the old version, + # and a title release-please cannot parse would silently cut no release at all. + - name: Compare the title version with the committed version + env: + # The title is human input, so it is bound through the environment (never + # interpolated into the script) and matched against a strict semver pattern + # before it is read. + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + pattern='^release: ((0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?)$' + if [[ ! "$PR_TITLE" =~ $pattern ]]; then + echo "::error::Release PR title must be \"release: X.Y.Z\" with a full semver version, got: $PR_TITLE" + exit 1 + fi + title_version="${BASH_REMATCH[1]}" + manifest_version="$(jq -r '.["."]' .release-please-manifest.json)" + if [[ "$title_version" != "$manifest_version" ]]; then + echo "::error::Release PR title says $title_version but the pull request is versioned $manifest_version. Wait for the release PR to be re-rendered at $title_version before merging." + exit 1 + fi + echo "Release PR title and committed version agree on $title_version." + + apply-title-version: + name: Apply edited release version + # A human retitle of the open release PR is bridged into the canonical explicit-version + # mechanism (a Release-As commit on scalar-next, which the platform re-renders the + # release PR from). `changes.title` is only set when the title itself changed, and bot + # senders are ignored so the platform's own retitles cannot bounce back into another + # commit. + # + # Both signals are required here, unlike the read-only check above, and each covers what the + # other cannot. The author, because this job pushes with `contents: write` and a title is + # free text — anyone able to open a pull request against main could otherwise + # name a version and have it committed to scalar-next. `user.login` is set by GitHub when + # the pull request is opened and cannot be forged by whoever edits the title afterwards. + # The title, because those accounts open pull requests other than release PRs, and retitling + # one of those must not push a release. + # + # One login per platform deployment, since a repo generated by staging carries staging's + # app. Parenthesised because the group is ANDed with the title clause below: without the + # parens that `&&` would bind to the last login alone, letting the other accounts push a + # release off any title. Listed rather than matched on the shared `scalar-docs` stem — a + # prefix test would also admit any future `scalar-docs-*[bot]`, including someone else's. + if: >- + ${{ github.event.action == 'edited' + && github.event.changes.title != null + && github.event.sender.type != 'Bot' + && github.event.pull_request.state == 'open' + && github.event.pull_request.base.ref == 'main' + && (github.event.pull_request.user.login == 'scalar-docs[bot]' + || github.event.pull_request.user.login == 'scalar-docs-staging[bot]' + || github.event.pull_request.user.login == 'scalar-docs-development[bot]') + && startsWith(github.event.pull_request.title, 'release: ') }} + # One bridge run at a time per pull request, newest retitle wins. Two retitles in quick + # succession (a version typo corrected seconds later) would otherwise start two runs that + # both read the version committed on the PR head, both get past the no-op guard, and both + # push — and since each fetches scalar-next immediately before committing, the second + # push fast-forwards instead of failing. release-please honours the newest Release-As + # footer, so the release would land on whichever run happened to push last, not on the + # title the maintainer actually left behind. + concurrency: + group: release-title-edit-${{ github.event.pull_request.number }} + cancel-in-progress: true + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # The PR head, so the version the pull request currently carries can be read before + # deciding whether anything needs to change. + ref: ${{ github.event.pull_request.head.sha }} + - name: Push a Release-As commit for the edited version + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + set -euo pipefail + pattern='^release: ((0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?)$' + if [[ ! "$PR_TITLE" =~ $pattern ]]; then + echo "::error::Release PR title must be \"release: X.Y.Z\" with a full semver version, got: $PR_TITLE" + exit 1 + fi + # Only ever a validated semver from here on, so it is safe in a commit message. + version="${BASH_REMATCH[1]}" + manifest_version="$(jq -r '.["."]' .release-please-manifest.json)" + # The re-rendered PR is retitled to the version it now carries; stopping here keeps + # that from producing an endless chain of Release-As commits. + if [[ "$version" == "$manifest_version" ]]; then + echo "This release PR already carries $version; nothing to do." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git fetch origin scalar-next + git checkout -B scalar-next origin/scalar-next + git commit --allow-empty -m "chore: release $version" -m "Release-As: $version" + # Plain (non-force) push: losing a race against a regeneration push fails loudly + # rather than discarding it, and the retitle can simply be repeated. + git push origin scalar-next + echo "Pushed Release-As: $version to scalar-next. The release PR will be re-rendered at that version." diff --git a/.github/workflows/sdk-ci.yml b/.github/workflows/sdk-ci.yml new file mode 100644 index 0000000..d9f0022 --- /dev/null +++ b/.github/workflows/sdk-ci.yml @@ -0,0 +1,27 @@ +name: Python SDK CI + +on: + push: + pull_request: + +# Least privilege for a verification-only workflow: every job below only reads the checked-out +# tree, so the run's GITHUB_TOKEN is narrowed to that regardless of the repository's default +# grants. Declared at the workflow level so a job added later inherits the floor. +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.11" + - run: python -m pip install --upgrade build + - run: python -m build + # Verification only, never auto-fix: the SDK is generated formatted, so a diff here means + # either hand-edited custom code or a regenerate that was not committed. ruff is pinned to + # the release that produced these bytes, since a formatter minor can change them. + - run: python -m pip install "ruff==0.16.8" + - run: ruff format --check . diff --git a/.github/workflows/sdk-release.yml b/.github/workflows/sdk-release.yml new file mode 100644 index 0000000..25d613d --- /dev/null +++ b/.github/workflows/sdk-release.yml @@ -0,0 +1,35 @@ +name: Python SDK Release + +on: + # Manual re-publish only: the automated publish for each release runs as the `publish` job + # inside release-please.yml, in the same run that cuts the tag (dispatching a workflow here + # instead would resolve it on the repository's default branch only, which breaks releasing + # from any other release line). Dispatch this workflow at an existing release tag to re-run + # a failed or skipped publish. A dispatched run is top-level, so OIDC trusted-publisher + # claims name this file; register it as an additional trusted publisher only when manual + # re-publishes are used. Never add a workflow_call trigger here — registries reject + # publishes from called (reusable) workflows. + workflow_dispatch: + +permissions: + contents: read + id-token: write + packages: write + +jobs: + release: + runs-on: ubuntu-latest + environment: production + env: + VERSIONING_POLICY: manual + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.11" + - run: python -m pip install --upgrade build + - run: python -m build + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 + with: + skip-existing: true diff --git a/.gitignore b/.gitignore index 3824f4c..e951962 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,10 @@ -.prism.log -.stdy.log -_dev - -__pycache__ -.mypy_cache - -dist - -.venv -.idea - -.env -.envrc -codegen.log -Brewfile.lock.json +# Generated by Scalar SDK Generator. +__pycache__/ +*.py[cod] +*.egg-info/ +.venv/ +/dist/ +/build/ +.mypy_cache/ +.pytest_cache/ +.ruff_cache/ diff --git a/.python-version b/.python-version deleted file mode 100644 index 43077b2..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.9.18 diff --git a/.stats.yml b/.stats.yml deleted file mode 100644 index 6d1924d..0000000 --- a/.stats.yml +++ /dev/null @@ -1,4 +0,0 @@ -configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/dedalus-labs/dedalus-c0e28b234478af75f61bcf42f5f32818d96ec93b1d8239fa0ff1c801c0e4b64f.yml -openapi_spec_hash: a70c391bb0957fc90c5dbf251de8afe4 -config_hash: fa45a5bf161b7291cb5ea20c2da83cc0 diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 5b01030..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.analysis.importFormat": "relative", -} diff --git a/Brewfile b/Brewfile deleted file mode 100644 index c43041c..0000000 --- a/Brewfile +++ /dev/null @@ -1,2 +0,0 @@ -brew "uv" - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 965581e..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,127 +0,0 @@ -## Setting up the environment - -### With `uv` - -We use [uv](https://docs.astral.sh/uv/) to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run: - -```sh -$ ./scripts/bootstrap -``` - -Or [install uv manually](https://docs.astral.sh/uv/getting-started/installation/) and run: - -```sh -$ uv sync --all-extras -``` - -You can then run scripts using `uv run python script.py` or by manually activating the virtual environment: - -```sh -# manually activate - https://docs.python.org/3/library/venv.html#how-venvs-work -$ source .venv/bin/activate - -# now you can omit the `uv run` prefix -$ python script.py -``` - -### Without `uv` - -Alternatively if you don't want to install `uv`, you can stick with the standard `pip` setup by ensuring you have the Python version specified in `.python-version`, create a virtual environment however you desire and then install dependencies using this command: - -```sh -$ pip install -r requirements-dev.lock -``` - -## Modifying/Adding code - -Most of the SDK is generated code. Modifications to code will be persisted between generations, but may -result in merge conflicts between manual patches and changes from the generator. The generator will never -modify the contents of the `src/dedalus_sdk/lib/` and `examples/` directories. - -## Adding and running examples - -All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. - -```py -# add an example to examples/.py - -#!/usr/bin/env -S uv run python -… -``` - -```sh -$ chmod +x examples/.py -# run the example against your api -$ ./examples/.py -``` - -## Using the repository from source - -If you’d like to use the repository from source, you can either install from git or link to a cloned repository: - -To install via git: - -```sh -$ pip install git+ssh://git@github.com/dedalus-labs/dedalus-python.git -``` - -Alternatively, you can build from source and install the wheel file: - -Building this package will create two files in the `dist/` directory, a `.tar.gz` containing the source files and a `.whl` that can be used to install the package efficiently. - -To create a distributable version of the library, all you have to do is run this command: - -```sh -$ uv build -# or -$ python -m build -``` - -Then to install: - -```sh -$ pip install ./path-to-wheel-file.whl -``` - -## Running tests - -Most tests require you to [set up a mock server](https://github.com/dgellow/steady) against the OpenAPI spec to run the tests. - -```sh -$ ./scripts/mock -``` - -```sh -$ ./scripts/test -``` - -## Linting and formatting - -This repository uses [ruff](https://github.com/astral-sh/ruff) and -[black](https://github.com/psf/black) to format the code in the repository. - -To lint: - -```sh -$ ./scripts/lint -``` - -To format and fix all ruff issues automatically: - -```sh -$ ./scripts/format -``` - -## Publishing and releases - -Changes made to this repository via the automated release PR pipeline should publish to PyPI automatically. If -the changes aren't made through the automated pipeline, you may want to make releases manually. - -### Publish with a GitHub workflow - -You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/dedalus-labs/dedalus-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. - -### Publish manually - -If you need to manually release a package, you can run the `bin/publish-pypi` script with a `PYPI_TOKEN` set on -the environment. diff --git a/LICENSE b/LICENSE index 3aa6139..d6e38b3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,201 @@ -Copyright 2026 Dedalus + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + 1. Definitions. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Dedalus + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 0d2e4f5..37954ee 100644 --- a/README.md +++ b/README.md @@ -1,468 +1,219 @@ -# Dedalus Python API library +# Dedalus - -[![PyPI version](https://img.shields.io/pypi/v/dedalus-sdk.svg?label=pypi%20(stable))](https://pypi.org/project/dedalus-sdk/) +This library provides convenient access to the Dedalus REST API from Python. -The Dedalus Python library provides convenient access to the Dedalus REST API from any Python 3.9+ -application. The library includes type definitions for all request params and response fields, -and offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx). +The full API of this library can be found in [api.md](./api.md). -It is generated with [Stainless](https://www.stainless.com/). +
-## MCP Server +## Contents -Use the Dedalus MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. +- [Installation](#installation) +- [Usage](#usage) +- [API Reference](./api.md) +- [Async](#async) +- [Streaming](#streaming) +- [WebSockets](#websockets) +- [Authentication](#authentication) +- [Errors](#errors) +- [Client Options](#client-options) +- [Retries and Timeouts](#retries-and-timeouts) +- [Pagination](#pagination) +- [Helpers](#helpers) +- [Logging](#logging) +- [Requirements](#requirements) -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=dedalus-mcp&config=eyJuYW1lIjoiZGVkYWx1cy1tY3AiLCJ0cmFuc3BvcnQiOiJodHRwIiwidXJsIjoiaHR0cHM6Ly9kZWRhbHVzLnN0bG1jcC5jb20iLCJoZWFkZXJzIjp7IngtYXBpLWtleSI6Ik15IFggQVBJIEtleSIsIngtZGVkYWx1cy1hcGkta2V5IjoiTXkgQVBJIEtleSJ9fQ) -[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22dedalus-mcp%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fdedalus.stlmcp.com%22%2C%22headers%22%3A%7B%22x-api-key%22%3A%22My%20X%20API%20Key%22%2C%22x-dedalus-api-key%22%3A%22My%20API%20Key%22%7D%7D) - -> Note: You may need to set environment variables in your MCP client. - -## Documentation - -The REST API documentation can be found on [docs.dedaluslabs.ai](https://docs.dedaluslabs.ai). The full API of this library can be found in [api.md](api.md). +
## Installation ```sh -# install from PyPI pip install dedalus-sdk ``` -## Usage +
-The full API of this library can be found in [api.md](api.md). +## Usage ```python import os + from dedalus_sdk import Dedalus client = Dedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), # This is the default and can be omitted + api_key=os.environ.get("DEDALUS_API_KEY"), ) machine = client.machines.create( - memory_mib=2048, + autosleep="300s", + memory_mib=4096, storage_gib=10, vcpu=1, + idempotency_key="", ) + print(machine.machine_id) ``` -While you can provide a `x_api_key` keyword argument, -we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/) -to add `DEDALUS_X_API_KEY="My X API Key"` to your `.env` file -so that your X API Key is not stored in source control. +The examples in the following sections assume a `client` configured as shown above. + +See the [API reference](./api.md) for every available operation. + +
-## Async usage +## Async -Simply import `AsyncDedalus` instead of `Dedalus` and use `await` with each API call: +Every client has an `Async` counterpart (`AsyncDedalus`) exposing the same resource tree with `await`. ```python -import os import asyncio -from dedalus_sdk import AsyncDedalus -client = AsyncDedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), # This is the default and can be omitted -) +from dedalus_sdk import AsyncDedalus async def main() -> None: + client = AsyncDedalus() machine = await client.machines.create( - memory_mib=2048, + autosleep="300s", + memory_mib=4096, storage_gib=10, vcpu=1, + idempotency_key="", ) - print(machine.machine_id) asyncio.run(main()) ``` -Functionality between the synchronous and asynchronous clients is otherwise identical. - -### With aiohttp +
-By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend. - -You can enable this by installing `aiohttp`: - -```sh -# install from PyPI -pip install dedalus-sdk[aiohttp] -``` +## Streaming -Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: +Streaming endpoints return an async iterator that yields results as the server emits them. ```python -import os -import asyncio -from dedalus_sdk import DefaultAioHttpClient -from dedalus_sdk import AsyncDedalus - - -async def main() -> None: - async with AsyncDedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), # This is the default and can be omitted - http_client=DefaultAioHttpClient(), - ) as client: - machine = await client.machines.create( - memory_mib=2048, - storage_gib=10, - vcpu=1, - ) - print(machine.machine_id) - +stream = client.machines.watch( + machine_id="machineID", +) -asyncio.run(main()) +for machine in stream: + print(machine) ``` -## Using types +
-Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like: +## WebSockets -- Serializing back into JSON, `model.to_json()` -- Converting to a dictionary, `model.to_dict()` - -Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`. - -## Pagination - -List methods in the Dedalus API are paginated. - -This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually: +WebSocket endpoints open a persistent connection you can send messages to and receive messages from. ```python -from dedalus_sdk import Dedalus - -client = Dedalus() - -all_machines = [] -# Automatically fetches more pages as needed. -for machine in client.machines.list(): - # Do something with machine here - all_machines.append(machine) -print(all_machines) +with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: + message = connection.recv() + print(message) ``` -Or, asynchronously: +
-```python -import asyncio -from dedalus_sdk import AsyncDedalus +## Authentication -client = AsyncDedalus() +Pass credentials to the generated client constructor. Environment variables are read automatically when supported by the target runtime. +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `x_api_key` | `string \| provider` | - | API key authentication using X-API-Key header Defaults to DEDALUS_X_API_KEY. | +| `bearer_auth` | `string \| provider` | - | Dedalus API key in Authorization: Bearer . Defaults to DEDALUS_BEARER_AUTH. | +| `api_key` | `string \| provider` | - | API key authentication using Bearer token Defaults to DEDALUS_API_KEY. | -async def main() -> None: - all_machines = [] - # Iterate through items across all pages, issuing requests as needed. - async for machine in client.machines.list(): - all_machines.append(machine) - print(all_machines) +Declared schemes: +- `ApiKeyAuth` API key in header `x-api-key` +- `BearerAuth` bearer token +- `Bearer` bearer token -asyncio.run(main()) -``` +
-Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages: - -```python -first_page = await client.machines.list() -if first_page.has_next_page(): - print(f"will fetch next page using these details: {first_page.next_page_info()}") - next_page = await first_page.get_next_page() - print(f"number of items we just fetched: {len(next_page.items)}") - -# Remove `await` for non-async usage. -``` +## Errors -Or just work directly with the returned data: +Non-success responses throw generated API errors. Error objects expose status, headers, response body, and request metadata where the target runtime supports it. ```python -first_page = await client.machines.list() - -print(f"next page cursor: {first_page.next_cursor}") # => "next page cursor: ..." -for machine in first_page.items: - print(machine.machine_id) - -# Remove `await` for non-async usage. -``` - -## Handling errors - -When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `dedalus_sdk.APIConnectionError` is raised. - -When the API returns a non-success status code (that is, 4xx or 5xx -response), a subclass of `dedalus_sdk.APIStatusError` is raised, containing `status_code` and `response` properties. - -All errors inherit from `dedalus_sdk.APIError`. - -```python -import dedalus_sdk -from dedalus_sdk import Dedalus - -client = Dedalus() +from dedalus_sdk import APIStatusError try: - client.machines.create( - memory_mib=2048, + machine = client.machines.create( + autosleep="300s", + memory_mib=4096, storage_gib=10, vcpu=1, + idempotency_key="", ) -except dedalus_sdk.APIConnectionError as e: - print("The server could not be reached") - print(e.__cause__) # an underlying Exception, likely raised within httpx. -except dedalus_sdk.RateLimitError as e: - print("A 429 status code was received; we should back off a bit.") -except dedalus_sdk.APIStatusError as e: - print("Another non-200-range status code was received") - print(e.status_code) - print(e.response) +except APIStatusError as err: + print(err.status_code, err.message) + raise ``` -Error codes are as follows: - -| Status Code | Error Type | -| ----------- | -------------------------- | -| 400 | `BadRequestError` | -| 401 | `AuthenticationError` | -| 403 | `PermissionDeniedError` | -| 404 | `NotFoundError` | -| 422 | `UnprocessableEntityError` | -| 429 | `RateLimitError` | -| >=500 | `InternalServerError` | -| N/A | `APIConnectionError` | +Documented error statuses: `400`, `401`, `403`, `409`, `429`, `500`, `502`, `503`, `default`. -### Retries +
-Certain errors are automatically retried 2 times by default, with a short exponential backoff. -Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, -429 Rate Limit, and >=500 Internal errors are all retried by default. +## Client Options -You can use the `max_retries` option to configure or disable retry settings: +Configure the generated client by setting any of these options when you create it. ```python from dedalus_sdk import Dedalus -# Configure the default for all requests: -client = Dedalus( - # default is 2 - max_retries=0, -) - -# Or, configure per-request: -client.with_options(max_retries=5).machines.create( - memory_mib=2048, - storage_gib=10, - vcpu=1, -) -``` - -### Timeouts - -By default requests time out after 1 minute. You can configure this with a `timeout` option, -which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object: - -```python -from dedalus_sdk import Dedalus - -# Configure the default for all requests: -client = Dedalus( - # 20 seconds (default is 1 minute) - timeout=20.0, -) - -# More granular control: client = Dedalus( - timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0), -) - -# Override per-request: -client.with_options(timeout=5.0).machines.create( - memory_mib=2048, - storage_gib=10, - vcpu=1, -) -``` - -On timeout, an `APITimeoutError` is thrown. - -Note that requests that time out are [retried twice by default](#retries). - -## Advanced - -### Logging - -We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module. - -You can enable logging by setting the environment variable `DEDALUS_LOG` to `info`. - -```shell -$ export DEDALUS_LOG=info -``` - -Or to `debug` for more verbose logging. - -### How to tell whether `None` means `null` or missing - -In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`: - -```py -if response.my_field is None: - if 'my_field' not in response.model_fields_set: - print('Got json like {}, without a "my_field" key present at all.') - else: - print('Got json like {"my_field": null}.') -``` - -### Accessing raw response data (e.g. headers) - -The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g., - -```py -from dedalus_sdk import Dedalus - -client = Dedalus() -response = client.machines.with_raw_response.create( - memory_mib=2048, - storage_gib=10, - vcpu=1, + timeout=60.0, + max_retries=2, ) -print(response.headers.get('X-My-Header')) - -machine = response.parse() # get the object that `machines.create()` would have returned -print(machine.machine_id) ``` -These methods return an [`APIResponse`](https://github.com/dedalus-labs/dedalus-python/tree/main/src/dedalus_sdk/_response.py) object. +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `x_api_key` | `str \| None` | `os.environ.get("DEDALUS_X_API_KEY")` | API key authentication using X-API-Key header | +| `bearer_auth` | `str \| None` | `os.environ.get("DEDALUS_BEARER_AUTH")` | Dedalus API key in Authorization: Bearer . | +| `api_key` | `str \| None` | `os.environ.get("DEDALUS_API_KEY")` | API key authentication using Bearer token | +| `base_url` | `str \| httpx.URL \| None` | - | Override the default API base URL. | +| `timeout` | `float \| Timeout \| None` | `60.0` | Maximum time in seconds to wait for a response before aborting a request. | +| `max_retries` | `int` | `2` | Number of retries for temporary failures. | +| `default_headers` | `Mapping[str, str] \| None` | - | Headers sent with every request. | +| `default_query` | `Mapping[str, object] \| None` | - | Query parameters sent with every request. | -The async client returns an [`AsyncAPIResponse`](https://github.com/dedalus-labs/dedalus-python/tree/main/src/dedalus_sdk/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. +
-#### `.with_streaming_response` +## Retries and Timeouts -The above interface eagerly reads the full response body when you make the request, which may not always be what you want. +Generated clients support request timeouts and retry temporary failures such as network errors, 408, 409, 429, and 5xx responses. Retry delays honor `Retry-After` headers when present. Tune the retry and timeout client options shown above, or override them per request. -To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. - -```python -with client.machines.with_streaming_response.create( - memory_mib=2048, - storage_gib=10, - vcpu=1, -) as response: - print(response.headers.get("X-My-Header")) - - for line in response.iter_lines(): - print(line) -``` +
-The context manager is required so that the response will reliably be closed. - -### Making custom/undocumented requests - -This library is typed for convenient access to the documented API. - -If you need to access undocumented endpoints, params, or response properties, the library can still be used. - -#### Undocumented endpoints - -To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other -http verbs. Options on the client will be respected (such as retries) when making this request. - -```py -import httpx - -response = client.post( - "/foo", - cast_to=httpx.Response, - body={"my_param": True}, -) - -print(response.headers.get("x-foo")) -``` - -#### Undocumented request params - -If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request -options. - -#### Undocumented response properties - -To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You -can also get all the extra fields on the Pydantic model as a dict with -[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra). - -### Configuring the HTTP client - -You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including: - -- Support for [proxies](https://www.python-httpx.org/advanced/proxies/) -- Custom [transports](https://www.python-httpx.org/advanced/transports/) -- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality - -```python -import httpx -from dedalus_sdk import Dedalus, DefaultHttpxClient - -client = Dedalus( - # Or use the `DEDALUS_BASE_URL` env var - base_url="http://my.test.server.example.com:8083", - http_client=DefaultHttpxClient( - proxy="http://my.test.proxy.example.com", - transport=httpx.HTTPTransport(local_address="0.0.0.0"), - ), -) -``` +## Pagination -You can also customize the client on a per-request basis by using `with_options()`: +List endpoints return paginated results you can iterate directly; the SDK fetches subsequent pages for you. ```python -client.with_options(http_client=DefaultHttpxClient(...)) +page = client.machines.list() ``` -### Managing HTTP resources - -By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting. +
-```py -from dedalus_sdk import Dedalus +## Helpers -with Dedalus() as client: - # make requests here - ... +- Use `client.with_raw_response..(...)` to access the raw `httpx.Response` and parse it yourself. +- Use `client.with_streaming_response..(...)` to stream a response body without buffering it. -# HTTP client is now closed -``` +
-## Versioning +## Logging -This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: +- Set the `DEDALUS_LOG` environment variable to `info` or `debug` to enable HTTP logging. +- Logs are emitted through the standard `logging` module under the `dedalus_sdk` logger. -1. Changes that only affect static types, without breaking runtime behavior. -2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ -3. Changes that we do not expect to impact the vast majority of users in practice. - -We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. - -We are keen for your feedback; please open an [issue](https://www.github.com/dedalus-labs/dedalus-python/issues) with questions, bugs, or suggestions. - -### Determining the installed version - -If you've upgraded to the latest version but aren't seeing any new features you were expecting then your python environment is likely still using an older version. - -You can determine the version that is being used at runtime with: - -```py -import dedalus_sdk -print(dedalus_sdk.__version__) -``` +
## Requirements -Python 3.9 or higher. - -## Contributing +- Python 3.8 or newer -See [the contributing documentation](./CONTRIBUTING.md). +Powered by Scalar. diff --git a/SECURITY.md b/SECURITY.md index 8efb336..b24e1dc 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,26 +2,18 @@ ## Reporting Security Issues -This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. +This is a generated Python SDK for Dedalus, produced by the Scalar SDK Generator (https://scalar.com). -To report a security issue, please contact the Stainless team at security@stainless.com. +If the issue is in the generated SDK itself — its runtime, authentication handling, path construction, or serialization — report it to the Scalar team at support@scalar.com. We will acknowledge the report, triage it for severity and impact, and communicate a timeline for a fix or an explanation if we decline it. ## Responsible Disclosure -We appreciate the efforts of security researchers and individuals who help us maintain the security of -SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible -disclosure practices by allowing us a reasonable amount of time to investigate and address the issue -before making any information public. +Please allow us reasonable time to investigate and address the issue before disclosing it publicly. Do not include credentials, tokens, or private API payloads in a public issue. -## Reporting Non-SDK Related Security Issues +## Reporting Non-SDK Security Issues -If you encounter security issues that are not directly related to SDKs but pertain to the services -or products provided by Dedalus, please follow the respective company's security reporting guidelines. - -### Dedalus Terms and Policies - -Please contact security@dedaluslabs.ai for any questions or concerns regarding the security of our services. +If the issue is in the Dedalus API or service rather than in this SDK, report it through the security process Dedalus has published. --- -Thank you for helping us keep the SDKs and systems they interact with secure. +Generated code validates emitted paths and escapes spec-derived strings, but OpenAPI documents should still be treated as untrusted input before generation. diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..5b31453 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,116 @@ +--- +name: dedalus-python-sdk +description: "Python SDK for Dedalus API. Use when writing Python code that calls Dedalus API with the dedalus-sdk package: installing it, constructing and authenticating the client, and calling API operations." +--- + +# Dedalus Python SDK + +Generated Python client for Dedalus API, published as `dedalus-sdk`. Use the generated client instead of hand-writing HTTP requests. + +## Install + +```sh +pip install dedalus-sdk +``` + +## Client setup and authentication + +```python +import os + +from dedalus_sdk import Dedalus + +client = Dedalus( + api_key=os.environ.get("DEDALUS_API_KEY"), +) +``` + +Provide credentials using the options below. Environment variables are read automatically when the target runtime supports them: + +- `x_api_key` (env: `DEDALUS_X_API_KEY`) — API key authentication using X-API-Key header +- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key in Authorization: Bearer . +- `api_key` (env: `DEDALUS_API_KEY`) — API key authentication using Bearer token + +## Calling operations + +```python +import os + +from dedalus_sdk import Dedalus + +client = Dedalus( + api_key=os.environ.get("DEDALUS_API_KEY"), +) + +machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", +) + +print(machine.machine_id) +``` + +Method names, parameter shapes, and response types are generated from the API description — do not guess them. Look up the exact call signature in [api.md](./api.md) before writing a call. + +## Pagination + +List endpoints return paginated results you can iterate directly; the SDK fetches subsequent pages for you. + +```python +page = client.machines.list() +``` + +## Streaming + +Streaming endpoints return an iterator that yields results as the server emits them. + +```python +stream = client.machines.watch( + machine_id="machineID", +) + +for machine in stream: + print(machine) +``` + +## WebSockets + +WebSocket endpoints open a persistent connection you can send messages to and receive messages from. + +```python +with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: + message = connection.recv() + print(message) +``` + +## Error handling + +Non-success responses throw generated API errors. Error objects expose status, headers, response body, and request metadata where the target runtime supports it. + +```python +from dedalus_sdk import APIStatusError + +try: + machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", + ) +except APIStatusError as err: + print(err.status_code, err.message) + raise +``` + +## Requirements + +- Python 3.8 or newer + +## Reference files + +- [README.md](./README.md) — full feature tour: client options, retries and timeouts, logging. +- [api.md](./api.md) — complete catalogue of every operation with request and response types. diff --git a/VERSIONING.md b/VERSIONING.md new file mode 100644 index 0000000..f9cf7dd --- /dev/null +++ b/VERSIONING.md @@ -0,0 +1,100 @@ +# Versioning + +This SDK is configured with the `manual` versioning policy. + +- `manual`: package versions are set explicitly before release. +- `semver`: releases should follow semantic versioning based on API and SDK surface changes. +- `calendar`: releases should use a calendar-derived version chosen by the release workflow or maintainer. + +## Branches and releases + +This repository follows a three-branch flow, managed by the Scalar platform together +with the generated workflows (which need only the default `GITHUB_TOKEN` — no extra +token required): + +- **`scalar-generated`** — pristine generator output. Pushed by the Scalar platform; do + not commit here. +- **`scalar-next`** — generated output merged with this repository's custom code. Commit + your customizations here (directly or via PRs). The Scalar platform merges each + regeneration into this branch and keeps the release PR up to date; merge conflicts + arrive as a PR from `scalar-merge-conflict` for you to resolve. +- **Default branch** — seeded from the first generated snapshot, then only ever receives + released states, each one the merge of a release PR. + +Release PRs are opened by the Scalar platform from `scalar-next` against the default +branch — so the PR diff shows the full pending release — and are versioned from +[Conventional Commits](https://www.conventionalcommits.org). Merging a release PR tags the +release, publishes it, and syncs the version bump and changelog back to `scalar-next`. +Pre-1.0, breaking changes bump the minor version. + +### Choosing an exact version + +To release a specific version — `1.0.0`, a hotfix number, anything the commit history would +not have picked — **edit the release PR title** to the version you want: + +```text +release: 1.0.0 +``` + +The `Release PR version` check turns red as soon as you save, because the version in the +title no longer matches the version committed in the PR. The Scalar platform then re-renders +the release PR at your version (changelog, manifest, and every version-bearing file), the +title comes back as `release: 1.0.0`, and the check turns green. **Wait for it to be green +before merging** — merging in between would tag a release whose own files still carry the +old version. + +The git-native equivalent, if you would rather not touch the PR: push an empty commit with a +`Release-As` footer to `scalar-next`. This is exactly what the title edit does for you. + +```sh +git commit --allow-empty -m "chore: release 1.0.0" -m "Release-As: 1.0.0" +``` + +### When a release PR does not merge cleanly + +Nothing is ever force-pushed automatically: a release PR that conflicts with the default +branch simply cannot be merged, and GitHub disables its merge button. The two causes have +different fixes: + +- **The default branch received direct commits** (for example a hotfix) that are not in + `scalar-next`. Land those commits on `scalar-next` (merge the default branch into it, or + cherry-pick), and the refreshed release PR merges cleanly again. Do not force-push — + that would discard the direct commits. +- **The repository was adopted with pre-existing content**, so the default branch shares + no history with `scalar-next`. The Scalar platform adds a checkbox to the release PR + description offering to replace the default branch with this release; checking it + authorizes the platform to force-push the released state over the old content. This is + destructive for anything on the default branch that never reached `scalar-next`, which + is why it requires that explicit opt-in. + +### Repository prerequisites + +- Branch protection on `scalar-next` and the default branch must allow the Scalar + platform and the `github-actions` bot to push (or be left unprotected); the default + branch only ever advances by merging release PRs, and `scalar-next` receives each + released state back from the release workflow. +- **`scalar-next` must not enable "Require linear history."** The Scalar platform merges each + regeneration into it, and merges a resolved conflict back the same way; the release sync + adds another merge whenever a release PR is squash- or rebase-merged. That setting rejects + all of them. +- No Actions settings changes are required: the generated workflows declare their own + permissions and never create pull requests. +- If this package publishes through OIDC trusted publishing (for example PyPI or npm), + register the trusted publisher on the registry against the **`release-please.yml`** + workflow filename. Merging a release PR publishes from the `publish` job inside that + same workflow run (checked out at the released tag), so the automated path's OIDC + claims name that file — and, because nothing is dispatched, releasing works from any + release branch, not only the repository default branch. `sdk-release.yml` exists for + manual re-publishes at an existing tag; register it as an additional trusted publisher + only if you use it. If the publish job is configured with a deployment environment, + include that environment in the registration too. + +### Recommended, not required + +Releases work without this; it closes a window where one can go out at the wrong version. + +- **If this repository uses auto-merge, make the `Release PR version` check a required status + check.** Auto-merge merges as soon as the checks that are *required* go green, with no + human present — so a check that is not required but still red at that moment stops + nothing, which is exactly the window between retitling a release PR and the platform + re-rendering it. diff --git a/api.md b/api.md index 7941ddf..b2335ae 100644 --- a/api.md +++ b/api.md @@ -1,71 +1,538 @@ -# Machines +# Dedalus Python API -Types: +Complete reference of every operation, grouped by resource. See [the README](./README.md) for usage and configuration. + +## Contents + +- [`Machines`](#machines) + - [List machines](#list-machines) + - [Create machine](#create-machine) + - [Get machine](#get-machine) + - [Update machine](#update-machine) + - [Destroy machine](#destroy-machine) + - [Watch machine lifecycle status](#watch-machine-lifecycle-status) + - [Sleep a running machine](#sleep-a-running-machine) + - [Wake a sleeping machine](#wake-a-sleeping-machine) + - [`Machines Network`](#machines-network) + - [Get machine network identity](#get-machine-network-identity) + - [`Machines Artifacts`](#machines-artifacts) + - [List artifacts](#list-artifacts) + - [Get artifact](#get-artifact) + - [Delete artifact](#delete-artifact) + - [`Machines Ports`](#machines-ports) + - [List ports](#list-ports) + - [Create port](#create-port) + - [Get port](#get-port) + - [Delete port](#delete-port) + - [`Machines Ssh`](#machines-ssh) + - [List SSH sessions](#list-ssh-sessions) + - [Create SSH session](#create-ssh-session) + - [Get SSH session](#get-ssh-session) + - [Delete SSH session](#delete-ssh-session) + - [`Machines Executions`](#machines-executions) + - [List executions](#list-executions) + - [Create execution](#create-execution) + - [Get execution](#get-execution) + - [Delete execution](#delete-execution) + - [Get execution output](#get-execution-output) + - [List execution events](#list-execution-events) + - [`Machines Terminals`](#machines-terminals) + - [List terminals](#list-terminals) + - [Create terminal](#create-terminal) + - [Get terminal](#get-terminal) + - [Delete terminal](#delete-terminal) + - [Connect to terminal WebSocket stream](#connect-to-terminal-websocket-stream) +- [`Networks`](#networks) + - [Get network details](#get-network-details) +- [`Usage`](#usage) + - [Get usage summary](#get-usage-summary) + - [List machine compute usage breakdown](#list-machine-compute-usage-breakdown) + - [List machine storage usage breakdown](#list-machine-storage-usage-breakdown) + +## Setup + +```python +import os + +from dedalus_sdk import Dedalus + +client = Dedalus( + api_key=os.environ.get("DEDALUS_API_KEY"), +) +``` + +## `Machines` + +### List machines + +| Direction | Type | +| --- | --- | +| Request | [`MachineListParams`](./src/dedalus_sdk/types/machine_list_params.py) | + +```python +page = client.machines.list() +``` + +### Create machine + +| Direction | Type | +| --- | --- | +| Request | [`MachineCreateParams`](./src/dedalus_sdk/types/machine_create_params.py) | +| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | + +```python +machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", +) +``` + +### Get machine + +| Direction | Type | +| --- | --- | +| Response | [`MachineRetrieveResponse`](./src/dedalus_sdk/types/machine_retrieve_response.py) | + +```python +machine = client.machines.retrieve( + machine_id="machineID", +) +``` + +### Update machine + +| Direction | Type | +| --- | --- | +| Request | [`MachineUpdateParams`](./src/dedalus_sdk/types/machine_update_params.py) | +| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | + +```python +machine = client.machines.update( + machine_id="machineID", + idempotency_key="", +) +``` + +### Destroy machine + +| Direction | Type | +| --- | --- | +| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | + +```python +machine = client.machines.delete( + machine_id="machineID", + idempotency_key="", +) +``` + +### Watch machine lifecycle status + +Streams machine lifecycle updates over Server-Sent Events. Each `status` event contains a full `LifecycleResponse` payload. The stream closes after the machine reaches its current desired state. + +| Direction | Type | +| --- | --- | +| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | + +```python +stream = client.machines.watch( + machine_id="machineID", +) + +for machine in stream: + print(machine) +``` + +### Sleep a running machine + +| Direction | Type | +| --- | --- | +| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | + +```python +machine = client.machines.sleep( + machine_id="machineID", + idempotency_key="", +) +``` + +### Wake a sleeping machine + +| Direction | Type | +| --- | --- | +| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | ```python -from dedalus_sdk.types import ( - CreateParams, - LifecycleStatus, - Machine, - MachineList, - MachineListItem, - UpdateParams, - MachineRetrieveResponse, +machine = client.machines.wake( + machine_id="machineID", + idempotency_key="", ) ``` -Methods: +### `Machines Network` + +#### Get machine network identity + +| Direction | Type | +| --- | --- | +| Response | [`MachineNetwork`](./src/dedalus_sdk/types/machines/machine_network.py) | + +```python +network = client.machines.network.retrieve( + machine_id="machineID", +) +``` + +### `Machines Artifacts` + +#### List artifacts + +| Direction | Type | +| --- | --- | +| Request | [`ArtifactListParams`](./src/dedalus_sdk/types/machines/artifact_list_params.py) | -- client.machines.create(\*\*params) -> Machine -- client.machines.retrieve(\*, machine_id) -> MachineRetrieveResponse -- client.machines.update(\*, machine_id, \*\*params) -> Machine -- client.machines.list(\*\*params) -> SyncCursorPage[MachineListItem] -- client.machines.delete(\*, machine_id) -> Machine -- client.machines.sleep(\*, machine_id) -> Machine -- client.machines.wake(\*, machine_id) -> Machine +```python +page = client.machines.artifacts.list( + machine_id="machineID", +) +``` -## SSH +#### Get artifact -Types: +| Direction | Type | +| --- | --- | +| Response | [`Artifact`](./src/dedalus_sdk/types/machines/artifact.py) | ```python -from dedalus_sdk.types.machines import ( - SSHConnection, - SSHHostTrust, - SSHSession, - SSHSessionCreateParams, - SSHSessionList, +artifact = client.machines.artifacts.retrieve( + machine_id="machineID", + artifact_id="artifactID", ) ``` -Methods: +#### Delete artifact + +| Direction | Type | +| --- | --- | +| Response | [`Artifact`](./src/dedalus_sdk/types/machines/artifact.py) | -- client.machines.ssh.create(\*, machine_id, \*\*params) -> SSHSession -- client.machines.ssh.retrieve(\*, machine_id, session_id) -> SSHSession -- client.machines.ssh.list(\*, machine_id, \*\*params) -> SyncCursorPage[SSHSession] -- client.machines.ssh.delete(\*, machine_id, session_id) -> SSHSession +```python +artifact = client.machines.artifacts.delete( + machine_id="machineID", + artifact_id="artifactID", + idempotency_key="", +) +``` -## Executions +### `Machines Ports` -Types: +#### List ports + +| Direction | Type | +| --- | --- | +| Request | [`PortListParams`](./src/dedalus_sdk/types/machines/port_list_params.py) | ```python -from dedalus_sdk.types.machines import ( - ArtifactRef, - Execution, - ExecutionCreateParams, - ExecutionEvent, - ExecutionEvents, - ExecutionList, - ExecutionOutput, +page = client.machines.ports.list( + machine_id="machineID", ) ``` -Methods: +#### Create port + +| Direction | Type | +| --- | --- | +| Request | [`PortCreateParams`](./src/dedalus_sdk/types/machines/port_create_params.py) | +| Response | [`Port`](./src/dedalus_sdk/types/machines/port.py) | + +```python +port = client.machines.ports.create( + machine_id="machineID", + port=0, + idempotency_key="", +) +``` + +#### Get port + +| Direction | Type | +| --- | --- | +| Response | [`Port`](./src/dedalus_sdk/types/machines/port.py) | + +```python +port = client.machines.ports.retrieve( + machine_id="machineID", + port_id="portID", +) +``` + +#### Delete port + +| Direction | Type | +| --- | --- | +| Response | [`Port`](./src/dedalus_sdk/types/machines/port.py) | + +```python +port = client.machines.ports.delete( + machine_id="machineID", + port_id="portID", + idempotency_key="", +) +``` + +### `Machines Ssh` + +#### List SSH sessions + +| Direction | Type | +| --- | --- | +| Request | [`SSHListParams`](./src/dedalus_sdk/types/machines/ssh_list_params.py) | + +```python +page = client.machines.ssh.list( + machine_id="machineID", +) +``` + +#### Create SSH session + +| Direction | Type | +| --- | --- | +| Request | [`SSHCreateParams`](./src/dedalus_sdk/types/machines/ssh_create_params.py) | +| Response | [`SSHSession`](./src/dedalus_sdk/types/machines/ssh_session.py) | + +```python +ssh = client.machines.ssh.create( + machine_id="machineID", + public_key="", + idempotency_key="", +) +``` -- client.machines.executions.create(\*, machine_id, \*\*params) -> Execution -- client.machines.executions.retrieve(\*, machine_id, execution_id) -> Execution -- client.machines.executions.list(\*, machine_id, \*\*params) -> SyncCursorPage[Execution] -- client.machines.executions.delete(\*, machine_id, execution_id) -> Execution -- client.machines.executions.events(\*, machine_id, execution_id, \*\*params) -> SyncCursorPage[ExecutionEvent] -- client.machines.executions.output(\*, machine_id, execution_id) -> ExecutionOutput +#### Get SSH session + +| Direction | Type | +| --- | --- | +| Response | [`SSHSession`](./src/dedalus_sdk/types/machines/ssh_session.py) | + +```python +ssh = client.machines.ssh.retrieve( + machine_id="machineID", + session_id="sessionID", +) +``` + +#### Delete SSH session + +| Direction | Type | +| --- | --- | +| Response | [`SSHSession`](./src/dedalus_sdk/types/machines/ssh_session.py) | + +```python +ssh = client.machines.ssh.delete( + machine_id="machineID", + session_id="sessionID", + idempotency_key="", +) +``` + +### `Machines Executions` + +#### List executions + +| Direction | Type | +| --- | --- | +| Request | [`ExecutionListParams`](./src/dedalus_sdk/types/machines/execution_list_params.py) | + +```python +page = client.machines.executions.list( + machine_id="machineID", +) +``` + +#### Create execution + +| Direction | Type | +| --- | --- | +| Request | [`ExecutionCreateParams`](./src/dedalus_sdk/types/machines/execution_create_params.py) | +| Response | [`Execution`](./src/dedalus_sdk/types/machines/execution.py) | + +```python +execution = client.machines.executions.create( + machine_id="machineID", + command=[""], + idempotency_key="", +) +``` + +#### Get execution + +| Direction | Type | +| --- | --- | +| Response | [`Execution`](./src/dedalus_sdk/types/machines/execution.py) | + +```python +execution = client.machines.executions.retrieve( + machine_id="machineID", + execution_id="executionID", +) +``` + +#### Delete execution + +| Direction | Type | +| --- | --- | +| Response | [`Execution`](./src/dedalus_sdk/types/machines/execution.py) | + +```python +execution = client.machines.executions.delete( + machine_id="machineID", + execution_id="executionID", + idempotency_key="", +) +``` + +#### Get execution output + +| Direction | Type | +| --- | --- | +| Response | [`ExecutionOutput`](./src/dedalus_sdk/types/machines/execution_output.py) | + +```python +execution = client.machines.executions.output( + machine_id="machineID", + execution_id="executionID", +) +``` + +#### List execution events + +| Direction | Type | +| --- | --- | +| Request | [`ExecutionEventsParams`](./src/dedalus_sdk/types/machines/execution_events_params.py) | + +```python +page = client.machines.executions.events( + machine_id="machineID", + execution_id="executionID", +) +``` + +### `Machines Terminals` + +#### List terminals + +| Direction | Type | +| --- | --- | +| Request | [`TerminalListParams`](./src/dedalus_sdk/types/machines/terminal_list_params.py) | + +```python +page = client.machines.terminals.list( + machine_id="machineID", +) +``` + +#### Create terminal + +| Direction | Type | +| --- | --- | +| Request | [`TerminalCreateParams`](./src/dedalus_sdk/types/machines/terminal_create_params.py) | +| Response | [`Terminal`](./src/dedalus_sdk/types/machines/terminal.py) | + +```python +terminal = client.machines.terminals.create( + machine_id="machineID", + height=0, + width=0, + idempotency_key="", +) +``` + +#### Get terminal + +| Direction | Type | +| --- | --- | +| Response | [`Terminal`](./src/dedalus_sdk/types/machines/terminal.py) | + +```python +terminal = client.machines.terminals.retrieve( + machine_id="machineID", + terminal_id="terminalID", +) +``` + +#### Delete terminal + +| Direction | Type | +| --- | --- | +| Response | [`Terminal`](./src/dedalus_sdk/types/machines/terminal.py) | + +```python +terminal = client.machines.terminals.delete( + machine_id="machineID", + terminal_id="terminalID", + idempotency_key="", +) +``` + +#### Connect to terminal WebSocket stream + +Upgrades to a WebSocket connection for interactive terminal I/O. Clients send JSON `TerminalClientEvent` messages and receive JSON `TerminalServerEvent` messages. Terminal byte streams are base64-encoded inside `input` and `output` events; `resize` events use integer `width` and `height` fields. + +```python +with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: + message = connection.recv() + print(message) +``` + +## `Networks` + +### Get network details + +| Direction | Type | +| --- | --- | +| Response | [`Network`](./src/dedalus_sdk/types/network.py) | + +```python +network = client.networks.retrieve( + network_id="networkID", +) +``` + +## `Usage` + +### Get usage summary + +| Direction | Type | +| --- | --- | +| Request | [`UsageRetrieveParams`](./src/dedalus_sdk/types/usage_retrieve_params.py) | +| Response | [`OrgUsage`](./src/dedalus_sdk/types/org_usage.py) | + +```python +usage = client.usage.retrieve() +``` + +### List machine compute usage breakdown + +| Direction | Type | +| --- | --- | +| Request | [`UsageMachineComputeParams`](./src/dedalus_sdk/types/usage_machine_compute_params.py) | +| Response | [`MachineComputeUsage`](./src/dedalus_sdk/types/machine_compute_usage.py) | + +```python +usage = client.usage.machine_compute() +``` + +### List machine storage usage breakdown + +| Direction | Type | +| --- | --- | +| Request | [`UsageMachineStorageParams`](./src/dedalus_sdk/types/usage_machine_storage_params.py) | +| Response | [`MachineStorageUsage`](./src/dedalus_sdk/types/machine_storage_usage.py) | + +```python +usage = client.usage.machine_storage() +``` diff --git a/bin/publish-pypi b/bin/publish-pypi deleted file mode 100644 index 5895700..0000000 --- a/bin/publish-pypi +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -set -eux -rm -rf dist -mkdir -p dist -uv build -if [ -n "${PYPI_TOKEN:-}" ]; then - uv publish --token=$PYPI_TOKEN -else - uv publish -fi diff --git a/examples/.keep b/examples/.keep deleted file mode 100644 index d8c73e9..0000000 --- a/examples/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store example files demonstrating usage of this SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 5e91b1b..0601588 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,13 @@ [project] name = "dedalus-sdk" -version = "0.5.0" -description = "The official Python library for the Dedalus API" -dynamic = ["readme"] -license = "MIT" +version = "0.1.0" # x-release-please-version +description = "Controlplane API for Dedalus Cloud Services (DCS)." +readme = "README.md" +license = "Apache-2.0" authors = [ -{ name = "Dedalus", email = "oss@dedaluslabs.ai" }, + { name = "Dedalus" }, ] - +requires-python = ">= 3.9" dependencies = [ "httpx>=0.23.0, <1", "pydantic>=1.9.0, <3", @@ -17,239 +17,16 @@ dependencies = [ "sniffio", ] -requires-python = ">= 3.9" -classifiers = [ - "Typing :: Typed", - "Intended Audience :: Developers", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", - "Operating System :: OS Independent", - "Operating System :: POSIX", - "Operating System :: MacOS", - "Operating System :: POSIX :: Linux", - "Operating System :: Microsoft :: Windows", - "Topic :: Software Development :: Libraries :: Python Modules", - "License :: OSI Approved :: MIT License" -] - -[project.urls] -Homepage = "https://github.com/dedalus-labs/dedalus-python" -Repository = "https://github.com/dedalus-labs/dedalus-python" - [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] - -[tool.uv] -managed = true -required-version = ">=0.9" -conflicts = [ - [ - { group = "pydantic-v1" }, - { group = "pydantic-v2" }, - ], -] - -[dependency-groups] -# version pins are in uv.lock -dev = [ - "pyright==1.1.399", - "mypy==1.17", - "respx", - "pytest", - "pytest-asyncio", - "ruff", - "time-machine", - "dirty-equals>=0.6.0", - "importlib-metadata>=6.7.0", - "rich>=13.7.1", - "pytest-xdist>=3.6.1", -] -pydantic-v1 = [ - "pydantic>=1.9.0,<2", -] -pydantic-v2 = [ - "pydantic~=2.0 ; python_full_version < '3.14'", - "pydantic~=2.12 ; python_full_version >= '3.14'", -] +websockets = ["websockets >= 13, < 16"] [build-system] -requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"] +requires = ["hatchling>=1.18.0"] build-backend = "hatchling.build" -[tool.hatch.build] -include = [ - "src/*" -] - [tool.hatch.build.targets.wheel] packages = ["src/dedalus_sdk"] -[tool.hatch.build.targets.sdist] -# Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc) -include = [ - "/*.toml", - "/*.json", - "/*.lock", - "/*.md", - "/mypy.ini", - "/noxfile.py", - "bin/*", - "examples/*", - "src/*", - "tests/*", -] - -[tool.hatch.metadata.hooks.fancy-pypi-readme] -content-type = "text/markdown" - -[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]] -path = "README.md" - -[[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]] -# replace relative links with absolute links -pattern = '\[(.+?)\]\(((?!https?://)\S+?)\)' -replacement = '[\1](https://github.com/dedalus-labs/dedalus-python/tree/main/\g<2>)' - -[tool.pytest.ini_options] -testpaths = ["tests"] -addopts = "--tb=short -n auto" -xfail_strict = true -asyncio_mode = "auto" -asyncio_default_fixture_loop_scope = "session" -filterwarnings = [ - "error" -] - -[tool.pyright] -# this enables practically every flag given by pyright. -# there are a couple of flags that are still disabled by -# default in strict mode as they are experimental and niche. -typeCheckingMode = "strict" -pythonVersion = "3.9" - -exclude = [ - "_dev", - ".venv", - ".nox", - ".git", -] - -reportImplicitOverride = true -reportOverlappingOverload = false - -reportImportCycles = false -reportPrivateUsage = false - -[tool.mypy] -pretty = true -show_error_codes = true - -# Exclude _files.py because mypy isn't smart enough to apply -# the correct type narrowing and as this is an internal module -# it's fine to just use Pyright. -# -# 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/.*"] - -strict_equality = true -implicit_reexport = true -check_untyped_defs = true -no_implicit_optional = true - -warn_return_any = true -warn_unreachable = true -warn_unused_configs = true - -# Turn these options off as it could cause conflicts -# with the Pyright options. -warn_unused_ignores = false -warn_redundant_casts = false - -disallow_any_generics = true -disallow_untyped_defs = true -disallow_untyped_calls = true -disallow_subclassing_any = true -disallow_incomplete_defs = true -disallow_untyped_decorators = true -cache_fine_grained = true - -# By default, mypy reports an error if you assign a value to the result -# of a function call that doesn't return anything. We do this in our test -# cases: -# ``` -# result = ... -# assert result is None -# ``` -# Changing this codegen to make mypy happy would increase complexity -# and would not be worth it. -disable_error_code = "func-returns-value,overload-cannot-match" - -# https://github.com/python/mypy/issues/12162 -[[tool.mypy.overrides]] -module = "black.files.*" -ignore_errors = true -ignore_missing_imports = true - - [tool.ruff] line-length = 120 -output-format = "grouped" -target-version = "py38" - -[tool.ruff.format] -docstring-code-format = true - -[tool.ruff.lint] -select = [ - # isort - "I", - # bugbear rules - "B", - # remove unused imports - "F401", - # check for missing future annotations - "FA102", - # bare except statements - "E722", - # unused arguments - "ARG", - # print statements - "T201", - "T203", - # misuse of typing.TYPE_CHECKING - "TC004", - # import rules - "TID251", -] -ignore = [ - # mutable defaults - "B006", -] -unfixable = [ - # disable auto fix for print statements - "T201", - "T203", -] - -extend-safe-fixes = ["FA102"] - -[tool.ruff.lint.flake8-tidy-imports.banned-api] -"functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" - -[tool.ruff.lint.isort] -length-sort = true -length-sort-straight = true -combine-as-imports = true -extra-standard-library = ["typing_extensions"] -known-first-party = ["dedalus_sdk", "tests"] - -[tool.ruff.lint.per-file-ignores] -"bin/**.py" = ["T201", "T203"] -"scripts/**.py" = ["T201", "T203"] -"tests/**.py" = ["T201", "T203"] -"examples/**.py" = ["T201", "T203"] diff --git a/release-please-config.json b/release-please-config.json index 65fbc85..36c59f4 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,16 +1,18 @@ { "packages": { - ".": {} + ".": { + "release-type": "python", + "extra-files": [ + "src/dedalus_sdk/_version.py" + ] + } }, - "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", - "include-v-in-tag": true, - "include-component-in-tag": false, - "versioning": "prerelease", - "prerelease": true, "bump-minor-pre-major": true, "bump-patch-for-minor-pre-major": false, - "pull-request-header": "Automated Release PR", + "include-component-in-tag": false, "pull-request-title-pattern": "release: ${version}", + "pull-request-header": "Automated Release PR", + "pull-request-footer": "The semver version number is based on included commit messages. To release a specific version,\nedit this pull request title to `release: 1.2.3` — Scalar re-creates this pull request at that\nversion, so wait for the `Release PR version` check to pass before merging.\n\nBrought to you by [Scalar](https://scalar.com)", "changelog-sections": [ { "type": "feat", @@ -36,34 +38,9 @@ "type": "docs", "section": "Documentation" }, - { - "type": "style", - "section": "Styles" - }, { "type": "refactor", "section": "Refactors" - }, - { - "type": "test", - "section": "Tests", - "hidden": true - }, - { - "type": "build", - "section": "Build System" - }, - { - "type": "ci", - "section": "Continuous Integration", - "hidden": true } - ], - "reviewers": [ - "@windsornguyen" - ], - "release-type": "python", - "extra-files": [ - "src/dedalus_sdk/_version.py" ] -} \ No newline at end of file +} diff --git a/requirements-dev.lock b/requirements-dev.lock deleted file mode 100644 index 7207341..0000000 --- a/requirements-dev.lock +++ /dev/null @@ -1,110 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv export -o requirements-dev.lock --no-hashes --e . -annotated-types==0.7.0 - # via pydantic -anyio==4.12.1 - # via - # dedalus-sdk - # httpx -backports-asyncio-runner==1.2.0 ; python_full_version < '3.11' - # via pytest-asyncio -certifi==2026.1.4 - # via - # httpcore - # httpx -colorama==0.4.6 ; sys_platform == 'win32' - # via pytest -dirty-equals==0.11 -distro==1.9.0 - # via dedalus-sdk -exceptiongroup==1.3.1 ; python_full_version < '3.11' - # via - # anyio - # pytest -execnet==2.1.2 - # via pytest-xdist -h11==0.16.0 - # via httpcore -httpcore==1.0.9 - # via httpx -httpx==0.28.1 - # via - # dedalus-sdk - # respx -idna==3.11 - # via - # anyio - # httpx -importlib-metadata==8.7.1 -iniconfig==2.1.0 ; python_full_version < '3.10' - # via pytest -iniconfig==2.3.0 ; python_full_version >= '3.10' - # via pytest -markdown-it-py==3.0.0 ; python_full_version < '3.10' - # via rich -markdown-it-py==4.0.0 ; python_full_version >= '3.10' - # via rich -mdurl==0.1.2 - # via markdown-it-py -mypy==1.17.0 -mypy-extensions==1.1.0 - # via mypy -nodeenv==1.10.0 - # via pyright -packaging==25.0 - # via pytest -pathspec==1.0.3 - # via mypy -pluggy==1.6.0 - # via pytest -pydantic==2.12.5 - # via dedalus-sdk -pydantic-core==2.41.5 - # via pydantic -pygments==2.19.2 - # via - # pytest - # rich -pyright==1.1.399 -pytest==8.4.2 ; python_full_version < '3.10' - # via - # pytest-asyncio - # pytest-xdist -pytest==9.0.2 ; python_full_version >= '3.10' - # via - # pytest-asyncio - # pytest-xdist -pytest-asyncio==1.2.0 ; python_full_version < '3.10' -pytest-asyncio==1.3.0 ; python_full_version >= '3.10' -pytest-xdist==3.8.0 -python-dateutil==2.9.0.post0 ; python_full_version < '3.10' - # via time-machine -respx==0.22.0 -rich==14.2.0 -ruff==0.14.13 -six==1.17.0 ; python_full_version < '3.10' - # via python-dateutil -sniffio==1.3.1 - # via dedalus-sdk -time-machine==2.19.0 ; python_full_version < '3.10' -time-machine==3.2.0 ; python_full_version >= '3.10' -tomli==2.4.0 ; python_full_version < '3.11' - # via - # mypy - # pytest -typing-extensions==4.15.0 - # via - # anyio - # dedalus-sdk - # exceptiongroup - # mypy - # pydantic - # pydantic-core - # pyright - # pytest-asyncio - # typing-inspection -typing-inspection==0.4.2 - # via pydantic -zipp==3.23.0 - # via importlib-metadata diff --git a/scalar-sdk.manifest.json b/scalar-sdk.manifest.json new file mode 100644 index 0000000..0ea24f3 --- /dev/null +++ b/scalar-sdk.manifest.json @@ -0,0 +1,9498 @@ +{ + "name": "Dedalus", + "slug": "dedalus", + "generatorVersion": "0.33.3", + "servers": [ + "https://dcs.dedaluslabs.ai" + ], + "environments": { + "production": "https://dcs.dedaluslabs.ai" + }, + "environmentOrder": [ + "production" + ], + "auth": [ + "apiKey", + "bearer", + "bearer" + ], + "authDetails": [ + { + "kind": "apiKey", + "id": "ApiKeyAuth", + "in": "header", + "paramName": "x-api-key" + }, + { + "kind": "bearer", + "id": "BearerAuth", + "bearerFormat": "Dedalus API key" + }, + { + "kind": "bearer", + "id": "Bearer" + } + ], + "clientHeaderParams": [], + "schemas": [ + { + "name": "artifact_list", + "source": "artifact_list", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "items", + "publicName": "items", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "artifact" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "next_cursor", + "publicName": "next_cursor", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "artifact_ref", + "source": "artifact_ref", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "artifact_id", + "publicName": "artifact_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "name", + "publicName": "name", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "artifact", + "source": "artifact", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "artifact_id", + "publicName": "artifact_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "created_at", + "publicName": "created_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "download_url", + "publicName": "download_url", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "execution_id", + "publicName": "execution_id", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "expires_at", + "publicName": "expires_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "mime_type", + "publicName": "mime_type", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "name", + "publicName": "name", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "sha256", + "publicName": "sha256", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "size_bytes", + "publicName": "size_bytes", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "execution_create_params", + "source": "execution_create_params", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "command", + "publicName": "command", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "primitive", + "type": "string" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "cwd", + "publicName": "cwd", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "env", + "publicName": "env", + "required": false, + "deprecated": false, + "type": { + "kind": "record", + "value": { + "kind": "primitive", + "type": "string" + }, + "propertyNames": { + "kind": "primitive", + "type": "string" + } + } + }, + { + "name": "stdin", + "publicName": "stdin", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "timeout_ms", + "publicName": "timeout_ms", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "create_params", + "source": "create_params", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "autosleep", + "publicName": "autosleep", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "memory_mib", + "publicName": "memory_mib", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "exclusiveMinimum": 0 + } + } + }, + { + "name": "storage_gib", + "publicName": "storage_gib", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "exclusiveMinimum": 0 + } + } + }, + { + "name": "vcpu", + "publicName": "vcpu", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "number", + "format": "double", + "validation": { + "exclusiveMinimum": 0 + } + } + } + ], + "additionalProperties": false + } + }, + { + "name": "port_create_params", + "source": "port_create_params", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "port", + "publicName": "port", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "protocol", + "publicName": "protocol", + "required": false, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "http", + "https" + ], + "names": [ + "HTTP", + "Https" + ], + "deprecations": [ + false, + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "ssh_session_create_params", + "source": "ssh_session_create_params", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "public_key", + "publicName": "public_key", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_create_params", + "source": "terminal_create_params", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "cwd", + "publicName": "cwd", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "env", + "publicName": "env", + "required": false, + "deprecated": false, + "type": { + "kind": "record", + "value": { + "kind": "primitive", + "type": "string" + }, + "propertyNames": { + "kind": "primitive", + "type": "string" + } + } + }, + { + "name": "height", + "publicName": "height", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "shell", + "publicName": "shell", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "width", + "publicName": "width", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "error_detail", + "source": "error_detail", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "location", + "publicName": "location", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "message", + "publicName": "message", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "value", + "publicName": "value", + "required": false, + "deprecated": false, + "type": { + "kind": "unknown" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "error_model", + "source": "error_model", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "detail", + "publicName": "detail", + "required": false, + "deprecated": false, + "extensions": { + "source": [ + "examples" + ], + "examples": "Property foo is required but is missing." + }, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "errors", + "publicName": "errors", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "error_detail" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "instance", + "publicName": "instance", + "required": false, + "deprecated": false, + "extensions": { + "source": [ + "examples" + ], + "examples": "https://example.com/error-log/abc123" + }, + "type": { + "kind": "primitive", + "type": "string", + "format": "uri" + } + }, + { + "name": "status", + "publicName": "status", + "required": false, + "deprecated": false, + "extensions": { + "source": [ + "examples" + ], + "examples": 400 + }, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "publicName": "title", + "required": false, + "deprecated": false, + "extensions": { + "source": [ + "examples" + ], + "examples": "Bad Request" + }, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "type", + "publicName": "type", + "required": false, + "deprecated": false, + "extensions": { + "source": [ + "examples" + ], + "examples": "https://example.com/errors/example" + }, + "type": { + "kind": "primitive", + "type": "string", + "format": "uri" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "execution_event", + "source": "execution_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "at", + "publicName": "at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "chunk", + "publicName": "chunk", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "error_code", + "publicName": "error_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "error_message", + "publicName": "error_message", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "exit_code", + "publicName": "exit_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "sequence", + "publicName": "sequence", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "signal", + "publicName": "signal", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "status", + "publicName": "status", + "required": false, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "wake_in_progress", + "queued", + "running", + "succeeded", + "failed", + "cancelled", + "expired" + ], + "names": [ + "WakeInProgress", + "Queued", + "Running", + "Succeeded", + "Failed", + "Cancelled", + "Expired" + ], + "deprecations": [ + false, + false, + false, + false, + false, + false, + false + ] + } + }, + { + "name": "type", + "publicName": "type", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "lifecycle", + "stdout", + "stderr" + ], + "names": [ + "Lifecycle", + "Stdout", + "Stderr" + ], + "deprecations": [ + false, + false, + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "execution_events", + "source": "execution_events", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "items", + "publicName": "items", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "execution_event" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "next_cursor", + "publicName": "next_cursor", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "execution_list", + "source": "execution_list", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "items", + "publicName": "items", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "execution" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "next_cursor", + "publicName": "next_cursor", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "execution_output", + "source": "execution_output", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "execution_id", + "publicName": "execution_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "stderr", + "publicName": "stderr", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "stderr_bytes", + "publicName": "stderr_bytes", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "stderr_truncated", + "publicName": "stderr_truncated", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + }, + { + "name": "stdout", + "publicName": "stdout", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "stdout_bytes", + "publicName": "stdout_bytes", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "stdout_truncated", + "publicName": "stdout_truncated", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "execution", + "source": "execution", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "artifacts", + "publicName": "artifacts", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "artifact_ref" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "command", + "publicName": "command", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "primitive", + "type": "string" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "completed_at", + "publicName": "completed_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_at", + "publicName": "created_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "cwd", + "publicName": "cwd", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "env_keys", + "publicName": "env_keys", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "primitive", + "type": "string" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "error_code", + "publicName": "error_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "error_message", + "publicName": "error_message", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "execution_id", + "publicName": "execution_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "exit_code", + "publicName": "exit_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "expires_at", + "publicName": "expires_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "retry_after_ms", + "publicName": "retry_after_ms", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "signal", + "publicName": "signal", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "started_at", + "publicName": "started_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "status", + "publicName": "status", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "wake_in_progress", + "queued", + "running", + "succeeded", + "failed", + "cancelled", + "expired" + ], + "names": [ + "WakeInProgress", + "Queued", + "Running", + "Succeeded", + "Failed", + "Cancelled", + "Expired" + ], + "deprecations": [ + false, + false, + false, + false, + false, + false, + false + ] + } + }, + { + "name": "stderr_bytes", + "publicName": "stderr_bytes", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "stderr_truncated", + "publicName": "stderr_truncated", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + }, + { + "name": "stdout_bytes", + "publicName": "stdout_bytes", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "stdout_truncated", + "publicName": "stdout_truncated", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine", + "source": "machine", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "autosleep_seconds", + "publicName": "autosleep_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 0, + "maximum": 9223372036 + } + } + }, + { + "name": "desired_state", + "publicName": "desired_state", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "running", + "sleeping", + "destroyed" + ], + "names": [ + "Running", + "Sleeping", + "Destroyed" + ], + "deprecations": [ + false, + false, + false + ] + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "memory_mib", + "publicName": "memory_mib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "phase", + "publicName": "phase", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "accepted", + "placement_pending", + "starting", + "running", + "stopping", + "sleeping", + "destroying", + "destroyed", + "failed" + ], + "names": [ + "Accepted", + "PlacementPending", + "Starting", + "Running", + "Stopping", + "Sleeping", + "Destroying", + "Destroyed", + "Failed" + ], + "deprecations": [ + false, + false, + false, + false, + false, + false, + false, + false, + false + ] + } + }, + { + "name": "storage_gib", + "publicName": "storage_gib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "vcpu", + "publicName": "vcpu", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "number", + "format": "double" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "lifecycle_status", + "source": "lifecycle_status", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "last_error", + "publicName": "last_error", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "last_progress_at", + "publicName": "last_progress_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "last_transition_at", + "publicName": "last_transition_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "phase", + "publicName": "phase", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "accepted", + "placement_pending", + "starting", + "running", + "stopping", + "sleeping", + "destroying", + "destroyed", + "failed" + ], + "names": [ + "Accepted", + "PlacementPending", + "Starting", + "Running", + "Stopping", + "Sleeping", + "Destroying", + "Destroyed", + "Failed" + ], + "deprecations": [ + false, + false, + false, + false, + false, + false, + false, + false, + false + ] + } + }, + { + "name": "reason", + "publicName": "reason", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "retryable", + "publicName": "retryable", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + }, + { + "name": "revision", + "publicName": "revision", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_compute_usage", + "source": "machine_compute_usage", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "granularity", + "publicName": "granularity", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "period_end", + "publicName": "period_end", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "period_start", + "publicName": "period_start", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "rows", + "publicName": "rows", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "machine_compute_usage_row" + } + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_compute_usage_row", + "source": "machine_compute_usage_row", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "awake_seconds", + "publicName": "awake_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "bucket_end", + "publicName": "bucket_end", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "bucket_start", + "publicName": "bucket_start", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "cpu_millicore_seconds", + "publicName": "cpu_millicore_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "last_window_end", + "publicName": "last_window_end", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "latest_meter_emitted_at", + "publicName": "latest_meter_emitted_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "memory_mib_seconds", + "publicName": "memory_mib_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "org_metering_bucket_ids", + "publicName": "org_metering_bucket_ids", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "primitive", + "type": "string" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "requested_memory_mib", + "publicName": "requested_memory_mib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int32" + } + }, + { + "name": "requested_storage_gib", + "publicName": "requested_storage_gib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int32" + } + }, + { + "name": "requested_vcpu", + "publicName": "requested_vcpu", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "number", + "format": "double" + } + }, + { + "name": "spec_fingerprint", + "publicName": "spec_fingerprint", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "window_count", + "publicName": "window_count", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_detail_response", + "source": "machine_detail_response", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "autosleep_seconds", + "publicName": "autosleep_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 0, + "maximum": 9223372036 + } + } + }, + { + "name": "desired_state", + "publicName": "desired_state", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "running", + "sleeping", + "destroyed" + ], + "names": [ + "Running", + "Sleeping", + "Destroyed" + ], + "deprecations": [ + false, + false, + false + ] + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "memory_mib", + "publicName": "memory_mib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "status", + "publicName": "status", + "required": true, + "deprecated": false, + "type": { + "kind": "ref", + "name": "lifecycle_status" + } + }, + { + "name": "storage_gib", + "publicName": "storage_gib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "vcpu", + "publicName": "vcpu", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "number", + "format": "double" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_id_path_segment", + "source": "machine_id_path_segment", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "validation": { + "pattern": "^dm-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", + "minLength": 4, + "maxLength": 253 + } + } + }, + { + "name": "machine_list_item", + "source": "machine_list_item", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "autosleep_seconds", + "publicName": "autosleep_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 0, + "maximum": 9223372036 + } + } + }, + { + "name": "created_at", + "publicName": "created_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "desired_state", + "publicName": "desired_state", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "running", + "sleeping", + "destroyed" + ], + "names": [ + "Running", + "Sleeping", + "Destroyed" + ], + "deprecations": [ + false, + false, + false + ] + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "memory_mib", + "publicName": "memory_mib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "phase", + "publicName": "phase", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "accepted", + "placement_pending", + "starting", + "running", + "stopping", + "sleeping", + "destroying", + "destroyed", + "failed" + ], + "names": [ + "Accepted", + "PlacementPending", + "Starting", + "Running", + "Stopping", + "Sleeping", + "Destroying", + "Destroyed", + "Failed" + ], + "deprecations": [ + false, + false, + false, + false, + false, + false, + false, + false, + false + ] + } + }, + { + "name": "storage_gib", + "publicName": "storage_gib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "vcpu", + "publicName": "vcpu", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "number", + "format": "double" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_list", + "source": "machine_list", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "items", + "publicName": "items", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "machine_list_item" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "next_cursor", + "publicName": "next_cursor", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_network", + "source": "machine_network", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "hostname", + "publicName": "hostname", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "network_id", + "publicName": "network_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "network_name", + "publicName": "network_name", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "private_ipv4", + "publicName": "private_ipv4", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "private_ipv6", + "publicName": "private_ipv6", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_storage_usage", + "source": "machine_storage_usage", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "period_end", + "publicName": "period_end", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "period_start", + "publicName": "period_start", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "rows", + "publicName": "rows", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "machine_storage_usage_row" + } + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_storage_usage_row", + "source": "machine_storage_usage_row", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "bucket_end", + "publicName": "bucket_end", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "bucket_start", + "publicName": "bucket_start", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "latest_meter_emitted_at", + "publicName": "latest_meter_emitted_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "logical_storage_bytes", + "publicName": "logical_storage_bytes", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "org_metering_bucket_id", + "publicName": "org_metering_bucket_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "storage_mib_seconds", + "publicName": "storage_mib_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "network_gateway", + "source": "network_gateway", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "hostname", + "publicName": "hostname", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "kind", + "publicName": "kind", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "ssh", + "port" + ], + "names": [ + "Ssh", + "Port" + ], + "deprecations": [ + false, + false + ] + } + }, + { + "name": "port", + "publicName": "port", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 1, + "maximum": 65535 + } + } + }, + { + "name": "protocol", + "publicName": "protocol", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "ssh", + "https" + ], + "names": [ + "Ssh", + "Https" + ], + "deprecations": [ + false, + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "network", + "source": "network", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "gateways", + "publicName": "gateways", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "network_gateway" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "name", + "publicName": "name", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "network_id", + "publicName": "network_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "port_list", + "source": "port_list", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "items", + "publicName": "items", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "port" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "next_cursor", + "publicName": "next_cursor", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "port", + "source": "port", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "created_at", + "publicName": "created_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "error_code", + "publicName": "error_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "error_message", + "publicName": "error_message", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "expires_at", + "publicName": "expires_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "port", + "publicName": "port", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "port_id", + "publicName": "port_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "protocol", + "publicName": "protocol", + "required": false, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "http", + "https" + ], + "names": [ + "HTTP", + "Https" + ], + "deprecations": [ + false, + false + ] + } + }, + { + "name": "ready_at", + "publicName": "ready_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "retry_after_ms", + "publicName": "retry_after_ms", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "status", + "publicName": "status", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "wake_in_progress", + "ready", + "closed", + "expired", + "failed" + ], + "names": [ + "WakeInProgress", + "Ready", + "Closed", + "Expired", + "Failed" + ], + "deprecations": [ + false, + false, + false, + false, + false + ] + } + }, + { + "name": "url", + "publicName": "url", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "public_path_segment", + "source": "public_path_segment", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "validation": { + "pattern": "^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$", + "minLength": 1, + "maxLength": 253 + } + } + }, + { + "name": "ssh_connection", + "source": "ssh_connection", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "endpoint", + "publicName": "endpoint", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "host_trust", + "publicName": "host_trust", + "required": false, + "deprecated": false, + "type": { + "kind": "ref", + "name": "ssh_host_trust" + } + }, + { + "name": "port", + "publicName": "port", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "ssh_username", + "publicName": "ssh_username", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "user_certificate", + "publicName": "user_certificate", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "ssh_host_trust", + "source": "ssh_host_trust", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "host_pattern", + "publicName": "host_pattern", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "kind", + "publicName": "kind", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "cert_authority" + ], + "names": [ + "CertAuthority" + ], + "deprecations": [ + false + ] + } + }, + { + "name": "public_key", + "publicName": "public_key", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "ssh_session_list", + "source": "ssh_session_list", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "items", + "publicName": "items", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "ssh_session" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "next_cursor", + "publicName": "next_cursor", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "ssh_session", + "source": "ssh_session", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "connection", + "publicName": "connection", + "required": false, + "deprecated": false, + "type": { + "kind": "ref", + "name": "ssh_connection" + } + }, + { + "name": "created_at", + "publicName": "created_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "error_code", + "publicName": "error_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "error_message", + "publicName": "error_message", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "expires_at", + "publicName": "expires_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "ready_at", + "publicName": "ready_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "retry_after_ms", + "publicName": "retry_after_ms", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "session_id", + "publicName": "session_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "status", + "publicName": "status", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "wake_in_progress", + "ready", + "closed", + "expired", + "failed" + ], + "names": [ + "WakeInProgress", + "Ready", + "Closed", + "Expired", + "Failed" + ], + "deprecations": [ + false, + false, + false, + false, + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_client_event", + "source": "terminal_client_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "ref", + "name": "terminal_input_event" + }, + { + "kind": "ref", + "name": "terminal_resize_event" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "input": "terminal_input_event", + "resize": "terminal_resize_event" + } + }, + "variantNames": [ + null, + null + ] + } + }, + { + "name": "terminal_closed_event", + "source": "terminal_closed_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "type", + "publicName": "type", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "closed" + ], + "names": [ + "Closed" + ], + "deprecations": [ + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_error_event", + "source": "terminal_error_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "error_code", + "publicName": "error_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "error_message", + "publicName": "error_message", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "type", + "publicName": "type", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "error" + ], + "names": [ + "Error" + ], + "deprecations": [ + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_input_event", + "source": "terminal_input_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "data", + "publicName": "data", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "byte" + } + }, + { + "name": "type", + "publicName": "type", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "input" + ], + "names": [ + "Input" + ], + "deprecations": [ + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_list", + "source": "terminal_list", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "items", + "publicName": "items", + "required": true, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "ref", + "name": "terminal" + } + }, + { + "kind": "null" + } + ] + } + }, + { + "name": "next_cursor", + "publicName": "next_cursor", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_output_event", + "source": "terminal_output_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "data", + "publicName": "data", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "byte" + } + }, + { + "name": "type", + "publicName": "type", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "output" + ], + "names": [ + "Output" + ], + "deprecations": [ + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_resize_event", + "source": "terminal_resize_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "height", + "publicName": "height", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "type", + "publicName": "type", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "resize" + ], + "names": [ + "Resize" + ], + "deprecations": [ + false + ] + } + }, + { + "name": "width", + "publicName": "width", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal", + "source": "terminal", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "created_at", + "publicName": "created_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "error_code", + "publicName": "error_code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "error_message", + "publicName": "error_message", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "expires_at", + "publicName": "expires_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "height", + "publicName": "height", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "machine_id", + "publicName": "machine_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "protocol", + "publicName": "protocol", + "required": false, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "websocket" + ], + "names": [ + "Websocket" + ], + "deprecations": [ + false + ] + } + }, + { + "name": "ready_at", + "publicName": "ready_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "retry_after_ms", + "publicName": "retry_after_ms", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "status", + "publicName": "status", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "wake_in_progress", + "ready", + "closed", + "expired", + "failed" + ], + "names": [ + "WakeInProgress", + "Ready", + "Closed", + "Expired", + "Failed" + ], + "deprecations": [ + false, + false, + false, + false, + false + ] + } + }, + { + "name": "stream_url", + "publicName": "stream_url", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "terminal_id", + "publicName": "terminal_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "width", + "publicName": "width", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "terminal_server_event", + "source": "terminal_server_event", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "ref", + "name": "terminal_output_event" + }, + { + "kind": "ref", + "name": "terminal_error_event" + }, + { + "kind": "ref", + "name": "terminal_closed_event" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "closed": "terminal_closed_event", + "error": "terminal_error_event", + "output": "terminal_output_event" + } + }, + "variantNames": [ + null, + null, + null + ] + } + }, + { + "name": "update_params", + "source": "update_params", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "autosleep", + "publicName": "autosleep", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "memory_mib", + "publicName": "memory_mib", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "storage_gib", + "publicName": "storage_gib", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "vcpu", + "publicName": "vcpu", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "number", + "format": "double" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "org_usage", + "source": "org_usage", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "billed_awake_seconds", + "publicName": "billed_awake_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "billed_cpu_millicore_seconds", + "publicName": "billed_cpu_millicore_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "billed_logical_storage_mib_seconds", + "publicName": "billed_logical_storage_mib_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "billed_memory_mib_seconds", + "publicName": "billed_memory_mib_seconds", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "included_storage_gib", + "publicName": "included_storage_gib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + }, + { + "name": "plan_slug", + "publicName": "plan_slug", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "provisioned_storage_gib", + "publicName": "provisioned_storage_gib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateResponseHeaders", + "source": "CreateResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateResponseHeaders", + "source": "CreateResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "RetrieveResponseHeaders", + "source": "RetrieveResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "UpdateResponseHeaders", + "source": "UpdateResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "UpdateResponseHeaders", + "source": "UpdateResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "DeleteResponseHeaders", + "source": "DeleteResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "DeleteResponseHeaders", + "source": "DeleteResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "SleepResponseHeaders", + "source": "SleepResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "SleepResponseHeaders", + "source": "SleepResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "WakeResponseHeaders", + "source": "WakeResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "WakeResponseHeaders", + "source": "WakeResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false + } + } + ], + "resources": [ + "machines", + "machines.network", + "machines.artifacts", + "machines.ports", + "machines.ssh", + "machines.executions", + "machines.terminals", + "networks", + "usage" + ], + "publicResources": [ + "machines", + "machines.network", + "machines.artifacts", + "machines.ports", + "machines.ssh", + "machines.executions", + "machines.terminals", + "networks", + "usage" + ], + "operations": [ + { + "resource": "machines", + "publicResource": "machines", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines", + "pathParams": [], + "publicPathParams": [], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "machine_list_item", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "create", + "publicOperation": "create", + "deprecated": false, + "method": "POST", + "path": "/v1/machines", + "pathParams": [], + "publicPathParams": [], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "publicBodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "bodyParamDetails": [ + { + "name": "autosleep", + "required": false + }, + { + "name": "memory_mib", + "required": false + }, + { + "name": "storage_gib", + "required": false + }, + { + "name": "vcpu", + "required": false + } + ], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "CreateResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine_detail_response", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "RetrieveResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "update", + "publicOperation": "update", + "deprecated": false, + "method": "PATCH", + "path": "/v1/machines/{machine_id}", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "publicBodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "bodyParamDetails": [ + { + "name": "autosleep", + "required": false + }, + { + "name": "memory_mib", + "required": false + }, + { + "name": "storage_gib", + "required": false + }, + { + "name": "vcpu", + "required": false + } + ], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineUpdateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "UpdateResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "delete", + "publicOperation": "delete", + "deprecated": false, + "method": "DELETE", + "path": "/v1/machines/{machine_id}", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineDeleteParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "DeleteResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "watch", + "publicOperation": "watch", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/status/stream", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id", + "Last-Event-ID" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id", + "Last-Event-ID" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + }, + { + "name": "Last-Event-ID", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineWatchParams" + }, + "response": { + "status": "200", + "contentType": "text/event-stream", + "encoding": "text", + "contents": [ + { + "contentType": "text/event-stream", + "encoding": "text" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + } + ], + "responseLinks": [], + "transport": "http", + "streaming": "sse" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "sleep", + "publicOperation": "sleep", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/sleep", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineSleepParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "SleepResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "wake", + "publicOperation": "wake", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/wake", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineWakeParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "WakeResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.network", + "publicResource": "machines.network", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/network", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "NetworkRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine_network", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.artifacts", + "publicResource": "machines.artifacts", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/artifacts", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ArtifactListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "artifact_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "artifact", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines.artifacts", + "publicResource": "machines.artifacts", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", + "pathParams": [ + "machine_id", + "artifact_id" + ], + "publicPathParams": [ + "machine_id", + "artifact_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "artifact_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ArtifactRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "artifact", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.artifacts", + "publicResource": "machines.artifacts", + "operation": "delete", + "publicOperation": "delete", + "deprecated": false, + "method": "DELETE", + "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", + "pathParams": [ + "machine_id", + "artifact_id" + ], + "publicPathParams": [ + "machine_id", + "artifact_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "artifact_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ArtifactDeleteParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "artifact", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.ports", + "publicResource": "machines.ports", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/ports", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "PortListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "port_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "port", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines.ports", + "publicResource": "machines.ports", + "operation": "create", + "publicOperation": "create", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/ports", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [ + "port", + "protocol" + ], + "publicBodyParams": [ + "port", + "protocol" + ], + "bodyParamDetails": [ + { + "name": "port", + "required": true + }, + { + "name": "protocol", + "required": false + } + ], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "PortCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "port", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.ports", + "publicResource": "machines.ports", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/ports/{port_id}", + "pathParams": [ + "machine_id", + "port_id" + ], + "publicPathParams": [ + "machine_id", + "port_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "port_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "PortRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "port", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.ports", + "publicResource": "machines.ports", + "operation": "delete", + "publicOperation": "delete", + "deprecated": false, + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ports/{port_id}", + "pathParams": [ + "machine_id", + "port_id" + ], + "publicPathParams": [ + "machine_id", + "port_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "port_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "PortDeleteParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "port", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "SshListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "ssh_session_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "ssh_session", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "create", + "publicOperation": "create", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/ssh", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [ + "public_key" + ], + "publicBodyParams": [ + "public_key" + ], + "bodyParamDetails": [ + { + "name": "public_key", + "required": true + } + ], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "SshCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "ssh_session", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "pathParams": [ + "machine_id", + "session_id" + ], + "publicPathParams": [ + "machine_id", + "session_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "session_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "SshRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "ssh_session", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "delete", + "publicOperation": "delete", + "deprecated": false, + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "pathParams": [ + "machine_id", + "session_id" + ], + "publicPathParams": [ + "machine_id", + "session_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "session_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "SshDeleteParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "ssh_session", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/executions", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ExecutionListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "execution_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "execution", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "create", + "publicOperation": "create", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/executions", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [ + "command", + "cwd", + "env", + "stdin", + "timeout_ms" + ], + "publicBodyParams": [ + "command", + "cwd", + "env", + "stdin", + "timeout_ms" + ], + "bodyParamDetails": [ + { + "name": "command", + "required": true + }, + { + "name": "cwd", + "required": false + }, + { + "name": "env", + "required": false + }, + { + "name": "stdin", + "required": false + }, + { + "name": "timeout_ms", + "required": false + } + ], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ExecutionCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "execution", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "pathParams": [ + "machine_id", + "execution_id" + ], + "publicPathParams": [ + "machine_id", + "execution_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ExecutionRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "execution", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "delete", + "publicOperation": "delete", + "deprecated": false, + "method": "DELETE", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "pathParams": [ + "machine_id", + "execution_id" + ], + "publicPathParams": [ + "machine_id", + "execution_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ExecutionDeleteParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "execution", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "output", + "publicOperation": "output", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", + "pathParams": [ + "machine_id", + "execution_id" + ], + "publicPathParams": [ + "machine_id", + "execution_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ExecutionOutputParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "execution_output", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "events", + "publicOperation": "events", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", + "pathParams": [ + "machine_id", + "execution_id" + ], + "publicPathParams": [ + "machine_id", + "execution_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "ExecutionEventsParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "execution_events", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "execution_event", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines.terminals", + "publicResource": "machines.terminals", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "TerminalListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "terminal_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "terminal", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines.terminals", + "publicResource": "machines.terminals", + "operation": "create", + "publicOperation": "create", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/terminals", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [ + "cwd", + "env", + "height", + "shell", + "width" + ], + "publicBodyParams": [ + "cwd", + "env", + "height", + "shell", + "width" + ], + "bodyParamDetails": [ + { + "name": "cwd", + "required": false + }, + { + "name": "env", + "required": false + }, + { + "name": "height", + "required": true + }, + { + "name": "shell", + "required": false + }, + { + "name": "width", + "required": true + } + ], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "TerminalCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "terminal", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.terminals", + "publicResource": "machines.terminals", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "pathParams": [ + "machine_id", + "terminal_id" + ], + "publicPathParams": [ + "machine_id", + "terminal_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "terminal_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "TerminalRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "terminal", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.terminals", + "publicResource": "machines.terminals", + "operation": "delete", + "publicOperation": "delete", + "deprecated": false, + "method": "DELETE", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "pathParams": [ + "machine_id", + "terminal_id" + ], + "publicPathParams": [ + "machine_id", + "terminal_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "terminal_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "TerminalDeleteParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "terminal", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.terminals", + "publicResource": "machines.terminals", + "operation": "connect", + "publicOperation": "connect", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", + "pathParams": [ + "machine_id", + "terminal_id" + ], + "publicPathParams": [ + "machine_id", + "terminal_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "terminal_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "TerminalConnectParams" + }, + "result": { + "successStatus": "101", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + } + ], + "responseLinks": [], + "transport": "websocket", + "websocket": { + "sendModel": { + "name": "terminal_client_event", + "publicAliases": [] + }, + "receiveModel": { + "name": "terminal_server_event", + "publicAliases": [] + }, + "eventNameSeparator": "." + } + }, + { + "resource": "networks", + "publicResource": "networks", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/networks/{network_id}", + "pathParams": [ + "network_id" + ], + "publicPathParams": [ + "network_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [ + "X-Dedalus-Org-Id" + ], + "publicHeaderParams": [ + "X-Dedalus-Org-Id" + ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "network_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [ + { + "name": "X-Dedalus-Org-Id", + "required": false, + "style": "form", + "explode": true + } + ], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "NetworkRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "network", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "usage", + "publicResource": "usage", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/usage", + "pathParams": [], + "publicPathParams": [], + "queryParams": [ + "period_start" + ], + "publicQueryParams": [ + "period_start" + ], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [ + { + "name": "period_start", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "UsageRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "org_usage", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "400", + "401", + "403", + "500", + "502", + "default" + ] + }, + "errorResponses": [ + { + "status": "400", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "500", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "502", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "usage", + "publicResource": "usage", + "operation": "machineCompute", + "publicOperation": "machineCompute", + "deprecated": false, + "method": "GET", + "path": "/v1/usage/machines/compute", + "pathParams": [], + "publicPathParams": [], + "queryParams": [ + "period_start", + "period_end", + "machine_id", + "granularity" + ], + "publicQueryParams": [ + "period_start", + "period_end", + "machine_id", + "granularity" + ], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [ + { + "name": "period_start", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "period_end", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "machine_id", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "granularity", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "UsageMachineComputeParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine_compute_usage", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "400", + "401", + "403", + "500", + "502", + "default" + ] + }, + "errorResponses": [ + { + "status": "400", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "500", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "502", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "usage", + "publicResource": "usage", + "operation": "machineStorage", + "publicOperation": "machineStorage", + "deprecated": false, + "method": "GET", + "path": "/v1/usage/machines/storage", + "pathParams": [], + "publicPathParams": [], + "queryParams": [ + "period_start", + "period_end", + "machine_id" + ], + "publicQueryParams": [ + "period_start", + "period_end", + "machine_id" + ], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [ + { + "name": "period_start", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "period_end", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "machine_id", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "UsageMachineStorageParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine_storage_usage", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "400", + "401", + "403", + "500", + "502", + "default" + ] + }, + "errorResponses": [ + { + "status": "400", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "500", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "502", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + } + ], + "webhooks": [] +} diff --git a/scripts/bootstrap b/scripts/bootstrap deleted file mode 100755 index 5a23841..0000000 --- a/scripts/bootstrap +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then - brew bundle check >/dev/null 2>&1 || { - echo -n "==> Install Homebrew dependencies? (y/N): " - read -r response - case "$response" in - [yY][eE][sS]|[yY]) - brew bundle - ;; - *) - ;; - esac - echo - } -fi - -echo "==> Installing Python…" -uv python install - -echo "==> Installing Python dependencies…" -uv sync --all-extras - -echo "==> Exporting Python dependencies…" -# note: `--no-hashes` is required because of https://github.com/pypa/pip/issues/4995 -uv export -o requirements-dev.lock --no-hashes diff --git a/scripts/format b/scripts/format deleted file mode 100755 index c8e1f69..0000000 --- a/scripts/format +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -echo "==> Running ruff" -uv run ruff format -uv run ruff check --fix . -# run formatting again to fix any inconsistencies when imports are stripped -uv run ruff format - -echo "==> Formatting docs" -uv run python scripts/utils/ruffen-docs.py README.md $(find . -type f -name api.md) diff --git a/scripts/lint b/scripts/lint deleted file mode 100755 index 371f4fa..0000000 --- a/scripts/lint +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -if [ "$1" = "--fix" ]; then - echo "==> Running ruff with --fix" - uv run ruff check . --fix -else - echo "==> Running ruff" - uv run ruff check . -fi - -echo "==> Running pyright" -uv run pyright -p . - -echo "==> Running mypy" -uv run mypy . - -echo "==> Making sure it imports" -uv run python -c 'import dedalus_sdk' diff --git a/scripts/mock b/scripts/mock deleted file mode 100755 index 6376077..0000000 --- a/scripts/mock +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -if [ "$1" == "--install" ]; then - npm exec --package=@stdy/cli@0.22.1 -- steady --version - exit 0 -fi - -if [[ -n "$1" && "$1" != '--'* ]]; then - URL="$1" - shift -else - URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" -fi - -# Check if the URL is empty -if [ -z "$URL" ]; then - echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" - exit 1 -fi - -echo "==> Starting mock server with URL ${URL}" - -# Run steady mock on the given spec -MOCK_PORT="${STAINLESS_MOCK_PORT:-4010}" - -if [ "$1" == "--daemon" ]; then - # Pre-install the package so the download doesn't eat into the startup timeout - npm exec --package=@stdy/cli@0.22.1 -- steady --version - - npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p "$MOCK_PORT" --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & - - # Wait for server to come online via health endpoint (max 30s) - echo -n "Waiting for server" - attempts=0 - while ! curl --silent --fail "http://127.0.0.1:$MOCK_PORT/_x-steady/health" >/dev/null 2>&1; do - if ! kill -0 $! 2>/dev/null; then - echo - cat .stdy.log - exit 1 - fi - attempts=$((attempts + 1)) - if [ "$attempts" -ge 300 ]; then - echo - echo "Timed out waiting for Steady server to start" - cat .stdy.log - exit 1 - fi - echo -n "." - sleep 0.1 - done - - echo -else - npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p "$MOCK_PORT" --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" -fi diff --git a/scripts/test b/scripts/test deleted file mode 100755 index caf18b7..0000000 --- a/scripts/test +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "$(dirname "$0")/.." - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[0;33m' -NC='\033[0m' # No Color - -MOCK_PORT="${STAINLESS_MOCK_PORT:-4010}" - -function steady_is_running() { - curl --silent "http://127.0.0.1:$MOCK_PORT/_x-steady/health" >/dev/null 2>&1 -} - -kill_server_on_port() { - pids=$(lsof -t -i tcp:"$1" || echo "") - if [ "$pids" != "" ]; then - kill "$pids" - echo "Stopped $pids." - fi -} - -function is_overriding_api_base_url() { - [ -n "$TEST_API_BASE_URL" ] -} - -if ! is_overriding_api_base_url && ! steady_is_running ; then - # When we exit this script, make sure to kill the background mock server process - trap 'kill_server_on_port "$MOCK_PORT"' EXIT - - # Start the dev server - ./scripts/mock --daemon -fi - -if is_overriding_api_base_url ; then - echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" - echo -elif ! steady_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server" - echo -e "running against your OpenAPI spec." - echo - echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the steady command:" - echo - echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.22.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p $MOCK_PORT --validator-query-array-format=repeat --validator-form-array-format=repeat --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" - echo - - exit 1 -else - echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}" - echo -fi - -if [ -n "${STAINLESS_MOCK_PORT:-}" ] && ! is_overriding_api_base_url ; then - export TEST_API_BASE_URL="http://127.0.0.1:$MOCK_PORT" -fi - -export DEFER_PYDANTIC_BUILD=false - -# Note that we need to specify the patch version here so that uv -# won't use unstable (alpha, beta, rc) releases for the tests -PY_VERSION_MIN=">=3.9.0" -PY_VERSION_MAX=">=3.14.0" - -function run_tests() { - echo "==> Running tests with Pydantic v2" - uv run --isolated --all-extras pytest "$@" - - # Skip Pydantic v1 tests on latest Python (not supported) - if [[ "$UV_PYTHON" != "$PY_VERSION_MAX" ]]; then - echo "==> Running tests with Pydantic v1" - uv run --isolated --all-extras --group=pydantic-v1 pytest "$@" - fi -} - -# If UV_PYTHON is already set in the environment, just run the command once -if [[ -n "$UV_PYTHON" ]]; then - run_tests "$@" -else - # If UV_PYTHON is not set, run the command for min and max versions - - echo "==> Running tests for Python $PY_VERSION_MIN" - UV_PYTHON="$PY_VERSION_MIN" run_tests "$@" - - echo "==> Running tests for Python $PY_VERSION_MAX" - UV_PYTHON="$PY_VERSION_MAX" run_tests "$@" -fi diff --git a/scripts/utils/ruffen-docs.py b/scripts/utils/ruffen-docs.py deleted file mode 100644 index 0cf2bd2..0000000 --- a/scripts/utils/ruffen-docs.py +++ /dev/null @@ -1,167 +0,0 @@ -# fork of https://github.com/asottile/blacken-docs adapted for ruff -from __future__ import annotations - -import re -import sys -import argparse -import textwrap -import contextlib -import subprocess -from typing import Match, Optional, Sequence, Generator, NamedTuple, cast - -MD_RE = re.compile( - r"(?P^(?P *)```\s*python\n)" r"(?P.*?)" r"(?P^(?P=indent)```\s*$)", - re.DOTALL | re.MULTILINE, -) -MD_PYCON_RE = re.compile( - r"(?P^(?P *)```\s*pycon\n)" r"(?P.*?)" r"(?P^(?P=indent)```.*$)", - re.DOTALL | re.MULTILINE, -) -PYCON_PREFIX = ">>> " -PYCON_CONTINUATION_PREFIX = "..." -PYCON_CONTINUATION_RE = re.compile( - rf"^{re.escape(PYCON_CONTINUATION_PREFIX)}( |$)", -) -DEFAULT_LINE_LENGTH = 100 - - -class CodeBlockError(NamedTuple): - offset: int - exc: Exception - - -def format_str( - src: str, -) -> tuple[str, Sequence[CodeBlockError]]: - errors: list[CodeBlockError] = [] - - @contextlib.contextmanager - def _collect_error(match: Match[str]) -> Generator[None, None, None]: - try: - yield - except Exception as e: - errors.append(CodeBlockError(match.start(), e)) - - def _md_match(match: Match[str]) -> str: - code = textwrap.dedent(match["code"]) - with _collect_error(match): - code = format_code_block(code) - code = textwrap.indent(code, match["indent"]) - return f"{match['before']}{code}{match['after']}" - - def _pycon_match(match: Match[str]) -> str: - code = "" - fragment = cast(Optional[str], None) - - def finish_fragment() -> None: - nonlocal code - nonlocal fragment - - if fragment is not None: - with _collect_error(match): - fragment = format_code_block(fragment) - fragment_lines = fragment.splitlines() - code += f"{PYCON_PREFIX}{fragment_lines[0]}\n" - for line in fragment_lines[1:]: - # Skip blank lines to handle Black adding a blank above - # functions within blocks. A blank line would end the REPL - # continuation prompt. - # - # >>> if True: - # ... def f(): - # ... pass - # ... - if line: - code += f"{PYCON_CONTINUATION_PREFIX} {line}\n" - if fragment_lines[-1].startswith(" "): - code += f"{PYCON_CONTINUATION_PREFIX}\n" - fragment = None - - indentation = None - for line in match["code"].splitlines(): - orig_line, line = line, line.lstrip() - if indentation is None and line: - indentation = len(orig_line) - len(line) - continuation_match = PYCON_CONTINUATION_RE.match(line) - if continuation_match and fragment is not None: - fragment += line[continuation_match.end() :] + "\n" - else: - finish_fragment() - if line.startswith(PYCON_PREFIX): - fragment = line[len(PYCON_PREFIX) :] + "\n" - else: - code += orig_line[indentation:] + "\n" - finish_fragment() - return code - - def _md_pycon_match(match: Match[str]) -> str: - code = _pycon_match(match) - code = textwrap.indent(code, match["indent"]) - return f"{match['before']}{code}{match['after']}" - - src = MD_RE.sub(_md_match, src) - src = MD_PYCON_RE.sub(_md_pycon_match, src) - return src, errors - - -def format_code_block(code: str) -> str: - return subprocess.check_output( - [ - sys.executable, - "-m", - "ruff", - "format", - "--stdin-filename=script.py", - f"--line-length={DEFAULT_LINE_LENGTH}", - ], - encoding="utf-8", - input=code, - ) - - -def format_file( - filename: str, - skip_errors: bool, -) -> int: - with open(filename, encoding="UTF-8") as f: - contents = f.read() - new_contents, errors = format_str(contents) - for error in errors: - lineno = contents[: error.offset].count("\n") + 1 - print(f"{filename}:{lineno}: code block parse error {error.exc}") - if errors and not skip_errors: - return 1 - if contents != new_contents: - print(f"{filename}: Rewriting...") - with open(filename, "w", encoding="UTF-8") as f: - f.write(new_contents) - return 0 - else: - return 0 - - -def main(argv: Sequence[str] | None = None) -> int: - parser = argparse.ArgumentParser() - parser.add_argument( - "-l", - "--line-length", - type=int, - default=DEFAULT_LINE_LENGTH, - ) - parser.add_argument( - "-S", - "--skip-string-normalization", - action="store_true", - ) - parser.add_argument("-E", "--skip-errors", action="store_true") - parser.add_argument("filenames", nargs="*") - args = parser.parse_args(argv) - - retv = 0 - for filename in args.filenames: - retv |= format_file(filename, skip_errors=args.skip_errors) - return retv - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh deleted file mode 100755 index 6d9fff5..0000000 --- a/scripts/utils/upload-artifact.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -set -exuo pipefail - -FILENAME=$(basename dist/*.whl) - -RESPONSE=$(curl -X POST "$URL?filename=$FILENAME" \ - -H "Authorization: Bearer $AUTH" \ - -H "Content-Type: application/json") - -SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') - -if [[ "$SIGNED_URL" == "null" ]]; then - echo -e "\033[31mFailed to get signed URL.\033[0m" - exit 1 -fi - -UPLOAD_RESPONSE=$(curl -v -X PUT \ - -H "Content-Type: binary/octet-stream" \ - --data-binary "@dist/$FILENAME" "$SIGNED_URL" 2>&1) - -if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then - echo -e "\033[32mUploaded build to Stainless storage.\033[0m" - echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/dedalus-python/$SHA/$FILENAME'\033[0m" -else - echo -e "\033[31mFailed to upload artifact.\033[0m" - exit 1 -fi diff --git a/src/dedalus/lib/.keep b/src/dedalus/lib/.keep deleted file mode 100644 index 5e2c99f..0000000 --- a/src/dedalus/lib/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store custom files to expand the SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/dedalus_sdk/__init__.py b/src/dedalus_sdk/__init__.py index 140521a..6521cc0 100644 --- a/src/dedalus_sdk/__init__.py +++ b/src/dedalus_sdk/__init__.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. import typing as _t @@ -24,10 +24,13 @@ InternalServerError, PermissionDeniedError, UnprocessableEntityError, + WebSocketConnectionClosedError, + WebSocketQueueFullError, APIResponseValidationError, ) from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient from ._utils._logs import setup_logging as _setup_logging +from .types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides __all__ = [ "types", @@ -71,6 +74,10 @@ "DefaultHttpxClient", "DefaultAsyncHttpxClient", "DefaultAioHttpClient", + "ReconnectingEvent", + "ReconnectingOverrides", + "WebSocketQueueFullError", + "WebSocketConnectionClosedError", ] if not _t.TYPE_CHECKING: @@ -78,15 +85,11 @@ _setup_logging() -# Update the __module__ attribute for exported symbols so that -# error messages point to this module instead of the module -# it was originally defined in, e.g. -# dedalus_sdk._exceptions.NotFoundError -> dedalus_sdk.NotFoundError __locals = locals() -for __name in __all__: - if not __name.startswith("__"): +__module_name = __name__ +for __export_name in __all__: + if not __export_name.startswith("__"): try: - __locals[__name].__module__ = "dedalus_sdk" + __locals[__export_name].__module__ = __module_name except (TypeError, AttributeError): - # Some of our exported symbols are builtins which we can't set attributes for. pass diff --git a/src/dedalus_sdk/_base_client.py b/src/dedalus_sdk/_base_client.py index 9507f5b..68e2617 100644 --- a/src/dedalus_sdk/_base_client.py +++ b/src/dedalus_sdk/_base_client.py @@ -13,10 +13,12 @@ import email.utils from types import TracebackType from random import random +from dataclasses import field, dataclass from typing import ( TYPE_CHECKING, Any, Dict, + List, Type, Union, Generic, @@ -115,10 +117,38 @@ HTTPX_DEFAULT_TIMEOUT = Timeout(5.0) +@dataclass +class CursorPageConfig: + """Per-operation cursor pagination descriptor baked into a page by the generated list method. + + The Python view of the shared, language-neutral descriptor: where the items array lives, how to + read the next cursor, which request param carries it, and on which carrier (query vs body). + Driving extraction from this config — rather than typed `items`/`next_cursor` model fields — lets + one page class serve every cursor scheme, including `cursor_id` (cursor read from the last item) + and body-carried cursors. + """ + + # Body path to the items array (e.g. ["items"], ["data"]). + items_path: List[str] = field(default_factory=list) + # "field" (a top-level response field) or "item" (a field on the last item — `cursor_id`). + cursor_kind: str = "field" + # Path to the cursor value: from the body root when cursor_kind is "field", or from the last item. + cursor_path: List[str] = field(default_factory=list) + # Request param wire name that carries the cursor. + cursor_param: str = "cursor" + # "query" or "body": the carrier the cursor param rides on the next request. + cursor_location: str = "query" + # Keep paginating across an empty page when set. + continue_on_empty_items: bool = False + # Body path to the scheme's `has_more` boolean. Only an explicit False stops pagination; + # a missing or non-boolean value falls back to cursor-presence semantics. + has_more_path: List[str] = field(default_factory=list) + + class PageInfo: """Stores the necessary information to build the request to retrieve the next page. - Either `url` or `params` must be set. + Exactly one of `url`, `params` (query carrier), or `json` (body carrier) must be set. """ url: URL | NotGiven @@ -180,6 +210,10 @@ class BasePage(GenericModel, Generic[_T]): _options: FinalRequestOptions = PrivateAttr() _model: Type[_T] = PrivateAttr() + # Per-operation cursor descriptor; set by the paginated method via _set_private_attributes and + # carried forward across pages so every page extracts items/cursor identically. None for pages + # that predate metadata-driven pagination. + _cursor_config: Optional[CursorPageConfig] = PrivateAttr(None) def has_next_page(self) -> bool: items = self._get_page_items() @@ -235,6 +269,7 @@ def _set_private_attributes( client: SyncAPIClient, model: Type[_T], options: FinalRequestOptions, + cursor_config: Optional[CursorPageConfig] = None, ) -> None: if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} @@ -242,6 +277,7 @@ def _set_private_attributes( self._model = model self._client = client self._options = options + self._cursor_config = cursor_config # Pydantic uses a custom `__iter__` method to support casting BaseModels # to dictionaries. e.g. dict(model). @@ -273,7 +309,10 @@ def get_next_page(self: SyncPageT) -> SyncPageT: ) options = self._info_to_options(info) - return self._client._request_api_list(self._model, page=self.__class__, options=options) + # Carry the cursor descriptor forward so the next page extracts items/cursor identically. + return self._client._request_api_list( + self._model, page=self.__class__, options=options, cursor_config=self._cursor_config + ) class AsyncPaginator(Generic[_T, AsyncPageT]): @@ -283,11 +322,13 @@ def __init__( options: FinalRequestOptions, page_cls: Type[AsyncPageT], model: Type[_T], + cursor_config: Optional[CursorPageConfig] = None, ) -> None: self._model = model self._client = client self._options = options self._page_cls = page_cls + self._cursor_config = cursor_config def __await__(self) -> Generator[Any, None, AsyncPageT]: return self._get_page().__await__() @@ -298,6 +339,7 @@ def _parser(resp: AsyncPageT) -> AsyncPageT: model=self._model, options=self._options, client=self._client, + cursor_config=self._cursor_config, ) return resp @@ -323,6 +365,7 @@ def _set_private_attributes( model: Type[_T], client: AsyncAPIClient, options: FinalRequestOptions, + cursor_config: Optional[CursorPageConfig] = None, ) -> None: if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None: self.__pydantic_private__ = {} @@ -330,6 +373,7 @@ def _set_private_attributes( self._model = model self._client = client self._options = options + self._cursor_config = cursor_config async def __aiter__(self) -> AsyncIterator[_T]: async for page in self.iter_pages(): @@ -353,7 +397,10 @@ async def get_next_page(self: AsyncPageT) -> AsyncPageT: ) options = self._info_to_options(info) - return await self._client._request_api_list(self._model, page=self.__class__, options=options) + # Carry the cursor descriptor forward so the next page extracts items/cursor identically. + return await self._client._request_api_list( + self._model, page=self.__class__, options=options, cursor_config=self._cursor_config + ) _HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient]) @@ -432,13 +479,13 @@ def _make_status_error( ) -> _exceptions.APIStatusError: raise NotImplementedError() - def _auth_headers( + def _auth_query( self, security: SecurityOptions, # noqa: ARG002 ) -> dict[str, str]: return {} - def _auth_query( + def _auth_cookies( self, security: SecurityOptions, # noqa: ARG002 ) -> dict[str, str]: @@ -448,12 +495,25 @@ def _custom_auth( self, security: SecurityOptions, # noqa: ARG002 ) -> httpx.Auth | None: - return None + # Single hook for custom httpx auth on both the sync and async request paths. It defaults to + # the legacy public `custom_auth` property so subclasses that already override that property + # keep applying identically on both paths; override `_custom_auth` itself to layer + # per-operation, security-aware auth on top. + return self.custom_auth - def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers: + def _build_headers( + self, + options: FinalRequestOptions, + *, + params: Query, + cookies: Mapping[str, str], + retries_taken: int = 0, + ) -> httpx.Headers: custom_headers = options.headers or {} - headers_dict = _merge_mappings({**self._auth_headers(options.security), **self.default_headers}, custom_headers) - self._validate_headers(headers_dict, custom_headers) + # Auth headers are folded into `default_headers` (matching the reference SDKs), so + # merging `default_headers` here already applies the configured credentials. + headers_dict = _merge_mappings(self.default_headers, custom_headers) + self._validate_headers(headers_dict, custom_headers, params, cookies) # headers are case-insensitive while dictionaries are not. headers = httpx.Headers(headers_dict) @@ -465,14 +525,14 @@ def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0 # Don't set these headers if they were already set or removed by the caller. We check # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case. lower_custom_headers = [header.lower() for header in custom_headers] - if "x-stainless-retry-count" not in lower_custom_headers: - headers["x-stainless-retry-count"] = str(retries_taken) - if "x-stainless-read-timeout" not in lower_custom_headers: + if "x-scalar-retry-count" not in lower_custom_headers: + headers["x-scalar-retry-count"] = str(retries_taken) + if "x-scalar-read-timeout" not in lower_custom_headers: timeout = self.timeout if isinstance(options.timeout, NotGiven) else options.timeout if isinstance(timeout, Timeout): timeout = timeout.read if timeout is not None: - headers["x-stainless-read-timeout"] = str(timeout) + headers["x-scalar-read-timeout"] = str(timeout) return headers @@ -523,8 +583,9 @@ def _build_request( else: raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`") - headers = self._build_headers(options, retries_taken=retries_taken) params = _merge_mappings({**self._auth_query(options.security), **self.default_query}, options.params) + cookies = self._auth_cookies(options.security) + headers = self._build_headers(options, retries_taken=retries_taken, params=params, cookies=cookies) content_type = headers.get("Content-Type") files = options.files @@ -597,6 +658,7 @@ def _build_request( # so that passing a `TypedDict` doesn't cause an error. # https://github.com/microsoft/pyright/issues/3526#event-6715453066 params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None, + cookies=cookies or None, **kwargs, ) @@ -693,6 +755,7 @@ def default_headers(self) -> dict[str, str | Omit]: "Content-Type": "application/json", "User-Agent": self.user_agent, **self.platform_headers(), + **self.auth_headers, **self._custom_headers, } @@ -706,8 +769,10 @@ def _validate_headers( self, headers: Headers, # noqa: ARG002 custom_headers: Headers, # noqa: ARG002 + params: Query, # noqa: ARG002 + cookies: Mapping[str, str], # noqa: ARG002 ) -> None: - """Validate the given default headers and custom headers. + """Validate merged auth-bearing headers, query params, and cookies. Does nothing by default. """ @@ -825,7 +890,7 @@ def _should_retry(self, response: httpx.Response) -> bool: return False def _idempotency_key(self) -> str: - return f"stainless-python-retry-{uuid.uuid4()}" + return f"scalar-python-retry-{uuid.uuid4()}" class _DefaultHttpxClient(httpx.Client): @@ -874,6 +939,7 @@ def __init__( custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, _strict_response_validation: bool, + **kwargs: Any, ) -> None: if not is_given(timeout): # if the user passed in a custom http client with a non-default @@ -907,6 +973,8 @@ def __init__( base_url=base_url, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), + # Used by generated `with_options(_extra_kwargs=...)` for HTTPX client configuration. + **kwargs, ) def is_closed(self) -> bool: @@ -1173,12 +1241,14 @@ def _request_api_list( model: Type[object], page: Type[SyncPageT], options: FinalRequestOptions, + cursor_config: Optional[CursorPageConfig] = None, ) -> SyncPageT: def _parser(resp: SyncPageT) -> SyncPageT: resp._set_private_attributes( client=self, model=model, options=options, + cursor_config=cursor_config, ) return resp @@ -1381,11 +1451,15 @@ def get_api_list( model: Type[object], page: Type[SyncPageT], body: Body | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, method: str = "get", + cursor_config: Optional[CursorPageConfig] = None, ) -> SyncPageT: - opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options) - return self._request_api_list(model, page, opts) + opts = FinalRequestOptions.construct( + method=method, url=path, json_data=body, files=to_httpx_files(files), **options + ) + return self._request_api_list(model, page, opts, cursor_config=cursor_config) class _DefaultAsyncHttpxClient(httpx.AsyncClient): @@ -1457,6 +1531,7 @@ def __init__( http_client: httpx.AsyncClient | None = None, custom_headers: Mapping[str, str] | None = None, custom_query: Mapping[str, object] | None = None, + **kwargs: Any, ) -> None: if not is_given(timeout): # if the user passed in a custom http client with a non-default @@ -1490,6 +1565,8 @@ def __init__( base_url=base_url, # cast to a valid type because mypy doesn't understand our type narrowing timeout=cast(Timeout, timeout), + # Used by generated `with_options(_extra_kwargs=...)` for HTTPX client configuration. + **kwargs, ) def is_closed(self) -> bool: @@ -1596,8 +1673,9 @@ async def request( await self._prepare_request(request) kwargs: HttpxSendArgs = {} - if self.custom_auth is not None: - kwargs["auth"] = self.custom_auth + custom_auth = self._custom_auth(options.security) + if custom_auth is not None: + kwargs["auth"] = custom_auth if options.follow_redirects is not None: kwargs["follow_redirects"] = options.follow_redirects @@ -1757,8 +1835,9 @@ def _request_api_list( model: Type[_T], page: Type[AsyncPageT], options: FinalRequestOptions, + cursor_config: Optional[CursorPageConfig] = None, ) -> AsyncPaginator[_T, AsyncPageT]: - return AsyncPaginator(client=self, options=options, page_cls=page, model=model) + return AsyncPaginator(client=self, options=options, page_cls=page, model=model, cursor_config=cursor_config) @overload async def get( @@ -1958,11 +2037,15 @@ def get_api_list( model: Type[_T], page: Type[AsyncPageT], body: Body | None = None, + files: RequestFiles | None = None, options: RequestOptions = {}, method: str = "get", + cursor_config: Optional[CursorPageConfig] = None, ) -> AsyncPaginator[_T, AsyncPageT]: - opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options) - return self._request_api_list(model, page, opts) + opts = FinalRequestOptions.construct( + method=method, url=path, json_data=body, files=to_httpx_files(files), **options + ) + return self._request_api_list(model, page, opts, cursor_config=cursor_config) def make_request_options( @@ -2080,12 +2163,12 @@ def get_platform() -> Platform: @lru_cache(maxsize=None) def platform_headers(version: str, *, platform: Platform | None) -> Dict[str, str]: return { - "X-Stainless-Lang": "python", - "X-Stainless-Package-Version": version, - "X-Stainless-OS": str(platform or get_platform()), - "X-Stainless-Arch": str(get_architecture()), - "X-Stainless-Runtime": get_python_runtime(), - "X-Stainless-Runtime-Version": get_python_version(), + "X-Scalar-Lang": "python", + "X-Scalar-Package-Version": version, + "X-Scalar-OS": str(platform or get_platform()), + "X-Scalar-Arch": str(get_architecture()), + "X-Scalar-Runtime": get_python_runtime(), + "X-Scalar-Runtime-Version": get_python_version(), } diff --git a/src/dedalus_sdk/_client.py b/src/dedalus_sdk/_client.py index 53fbd0e..0ba30fe 100644 --- a/src/dedalus_sdk/_client.py +++ b/src/dedalus_sdk/_client.py @@ -1,8 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations import os +import threading from typing import TYPE_CHECKING, Any, Mapping from typing_extensions import Self, override @@ -20,42 +21,62 @@ RequestOptions, not_given, ) -from ._utils import ( - is_given, - is_mapping_t, - 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__ -from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError from ._base_client import ( DEFAULT_MAX_RETRIES, SyncAPIClient, AsyncAPIClient, ) +from ._streaming import Stream as Stream, AsyncStream as AsyncStream +from ._version import __version__ if TYPE_CHECKING: - from .resources import machines - from .resources.machines.machines import MachinesResource, AsyncMachinesResource + from .resources import machines, networks, usage + from .resources.machines import MachinesResource, AsyncMachinesResource + from .resources.networks import NetworksResource, AsyncNetworksResource + from .resources.usage import UsageResource, AsyncUsageResource + +# Serializes lazy resource imports so concurrent cold access from multiple +# threads cannot deadlock on CPython import locks (see CPython 3.14). +_RESOURCE_IMPORT_LOCK = threading.RLock() -__all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "Dedalus", "AsyncDedalus", "Client", "AsyncClient"] +__all__ = ["Dedalus", "AsyncDedalus", "Client", "AsyncClient", "Timeout", "Transport", "ProxiesTypes", "RequestOptions"] class Dedalus(SyncAPIClient): # client options api_key: str | None x_api_key: str | None + as_base_url: str | None dedalus_org_id: str | None + provider: str | None + provider_key: str | None + provider_model: str | None + bearer_auth: str | None + + websocket_base_url: str | httpx.URL | None + """Base URL for WebSocket connections. + + If not specified, the default base URL will be used, with 'wss://' replacing the + 'http://' or 'https://' scheme. For example: 'http://example.com' becomes + 'wss://example.com' + """ def __init__( self, *, api_key: str | None = None, x_api_key: str | None = None, + as_base_url: str | None = None, dedalus_org_id: str | None = None, + provider: str | None = None, + provider_key: str | None = None, + provider_model: str | None = None, + bearer_auth: str | None = None, base_url: str | httpx.URL | None = None, + websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, @@ -79,25 +100,43 @@ def __init__( This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `api_key` from `DEDALUS_API_KEY` - `x_api_key` from `DEDALUS_X_API_KEY` + - `as_base_url` from `DEDALUS_AS_URL` - `dedalus_org_id` from `DEDALUS_ORG_ID` + - `provider` from `DEDALUS_PROVIDER` + - `provider_key` from `DEDALUS_PROVIDER_KEY` + - `provider_model` from `DEDALUS_PROVIDER_MODEL` """ if api_key is None: api_key = os.environ.get("DEDALUS_API_KEY") self.api_key = api_key - if x_api_key is None: x_api_key = os.environ.get("DEDALUS_X_API_KEY") self.x_api_key = x_api_key - + if as_base_url is None: + as_base_url = os.environ.get("DEDALUS_AS_URL", "").strip() or None + if as_base_url is None: + as_base_url = "https://as.dedaluslabs.ai" + self.as_base_url = as_base_url if dedalus_org_id is None: dedalus_org_id = os.environ.get("DEDALUS_ORG_ID") self.dedalus_org_id = dedalus_org_id - + if provider is None: + provider = os.environ.get("DEDALUS_PROVIDER") + self.provider = provider + if provider_key is None: + provider_key = os.environ.get("DEDALUS_PROVIDER_KEY") + self.provider_key = provider_key + if provider_model is None: + provider_model = os.environ.get("DEDALUS_PROVIDER_MODEL") + self.provider_model = provider_model + if bearer_auth is None: + bearer_auth = os.environ.get("DEDALUS_BEARER_AUTH") + self.bearer_auth = bearer_auth + self.websocket_base_url = websocket_base_url if base_url is None: base_url = os.environ.get("DEDALUS_BASE_URL") if base_url is None: - base_url = f"https://dcs.dedaluslabs.ai" - + base_url = "https://dcs.dedaluslabs.ai" custom_headers_env = os.environ.get("DEDALUS_CUSTOM_HEADERS") if custom_headers_env is not None: parsed: dict[str, str] = {} @@ -106,7 +145,6 @@ def __init__( 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, @@ -117,15 +155,27 @@ def __init__( custom_query=default_query, _strict_response_validation=_strict_response_validation, ) - self._idempotency_header = "Idempotency-Key" + self._default_stream_cls = Stream @cached_property - def machines(self) -> MachinesResource: - from .resources.machines import MachinesResource - + def machines(self) -> "MachinesResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.machines import MachinesResource return MachinesResource(self) + @cached_property + def networks(self) -> "NetworksResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.networks import NetworksResource + return NetworksResource(self) + + @cached_property + def usage(self) -> "UsageResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.usage import UsageResource + return UsageResource(self) + @cached_property def with_raw_response(self) -> DedalusWithRawResponse: return DedalusWithRawResponse(self) @@ -137,53 +187,80 @@ def with_streaming_response(self) -> DedalusWithStreamedResponse: @property @override def qs(self) -> Querystring: - return Querystring(array_format="repeat") + return Querystring(array_format="comma") + @property @override - def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: - headers: dict[str, str] = {} - if security.get("api_key_auth", False): - for key, value in self._api_key_auth.items(): - headers.setdefault(key, value) - if security.get("bearer_auth", False): - for key, value in self._bearer_auth.items(): - headers.setdefault(key, value) - return headers + def auth_headers(self) -> dict[str, str]: + return { + **self._api_key_header_auth, + **self._x_api_key_header_auth, + **self._bearer_auth_header_auth, + } + + @override + def _auth_query(self, security: dict[str, bool]) -> dict[str, str]: + _ = security + return {} + + @override + def _auth_cookies(self, security: dict[str, bool]) -> dict[str, str]: + _ = security + return {} @property - def _api_key_auth(self) -> dict[str, str]: - x_api_key = self.x_api_key - if x_api_key is None: + def _api_key_header_auth(self) -> dict[str, str]: + value = self.api_key + if value is None: return {} - return {"x-api-key": x_api_key} + return {"Authorization": f"Bearer {value}"} @property - def _bearer_auth(self) -> dict[str, str]: - api_key = self.api_key - if api_key is None: + def _x_api_key_header_auth(self) -> dict[str, str]: + value = self.x_api_key + if value is None: + return {} + return {"x-api-key": value} + + @property + def _bearer_auth_header_auth(self) -> dict[str, str]: + value = self.bearer_auth + if value is None: return {} - return {"Authorization": f"Bearer {api_key}"} + return {"Authorization": f"Bearer {value}"} @property @override def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, - "X-Stainless-Async": "false", - "X-Dedalus-Org-Id": self.dedalus_org_id if self.dedalus_org_id is not None else Omit(), + "X-Scalar-Async": "false", + "User-Agent": "Dedalus-SDK", + "X-SDK-Version": "1.0.0", + "X-Provider": self.provider if self.provider is not None else Omit(), + "X-Provider-Key": self.provider_key if self.provider_key is not None else Omit(), + "X-Provider-Model": self.provider_model if self.provider_model is not None else Omit(), **self._custom_headers, } @override - def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None: - if headers.get("x-api-key") or isinstance(custom_headers.get("x-api-key"), Omit): + def _validate_headers( + self, + headers: Headers, + custom_headers: Headers, + params: Mapping[str, object], + cookies: Mapping[str, str], + ) -> None: + if headers.get("Authorization"): return - - if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit): + if isinstance(custom_headers.get("Authorization"), Omit): + return + if headers.get("x-api-key"): + return + if isinstance(custom_headers.get("x-api-key"), Omit): return - raise TypeError( - '"Could not resolve authentication method. Expected either x_api_key or api_key to be set. Or for one of the `x-api-key` or `Authorization` headers to be explicitly omitted"' + '"Could not resolve authentication method. Expected either api_key, bearer_auth or x_api_key to be set. Or for one of the `Authorization` or `x-api-key` headers to be explicitly omitted"' ) def copy( @@ -191,7 +268,13 @@ def copy( *, api_key: str | None = None, x_api_key: str | None = None, + as_base_url: str | None = None, dedalus_org_id: str | None = None, + provider: str | None = None, + provider_key: str | None = None, + provider_model: str | None = None, + bearer_auth: str | None = None, + websocket_base_url: str | httpx.URL | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, @@ -202,74 +285,60 @@ def copy( set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: - """ - Create a new client instance re-using the same options given to the current client with optional overriding. - """ + """Create a new client reusing this client's options with optional overrides.""" if default_headers is not None and set_default_headers is not None: raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") - if default_query is not None and set_default_query is not None: raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") - headers = self._custom_headers if default_headers is not None: headers = {**headers, **default_headers} elif set_default_headers is not None: headers = set_default_headers - params = self._custom_query if default_query is not None: params = {**params, **default_query} elif set_default_query is not None: params = set_default_query - http_client = http_client or self._client return self.__class__( api_key=api_key or self.api_key, x_api_key=x_api_key or self.x_api_key, + as_base_url=as_base_url or self.as_base_url, dedalus_org_id=dedalus_org_id or self.dedalus_org_id, + provider=provider or self.provider, + provider_key=provider_key or self.provider_key, + provider_model=provider_model or self.provider_model, + bearer_auth=bearer_auth or self.bearer_auth, + websocket_base_url=websocket_base_url or self.websocket_base_url, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, + _strict_response_validation=self._strict_response_validation, **_extra_kwargs, ) - # Alias for `copy` for nicer inline usage, e.g. - # client.with_options(timeout=10).foo.create(...) with_options = copy @override - def _make_status_error( - self, - err_msg: str, - *, - body: object, - response: httpx.Response, - ) -> APIStatusError: + def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Response) -> APIStatusError: if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=body) - if response.status_code == 401: return _exceptions.AuthenticationError(err_msg, response=response, body=body) - if response.status_code == 403: return _exceptions.PermissionDeniedError(err_msg, response=response, body=body) - if response.status_code == 404: return _exceptions.NotFoundError(err_msg, response=response, body=body) - if response.status_code == 409: return _exceptions.ConflictError(err_msg, response=response, body=body) - if response.status_code == 422: return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body) - if response.status_code == 429: return _exceptions.RateLimitError(err_msg, response=response, body=body) - if response.status_code >= 500: return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) @@ -279,15 +348,34 @@ class AsyncDedalus(AsyncAPIClient): # client options api_key: str | None x_api_key: str | None + as_base_url: str | None dedalus_org_id: str | None + provider: str | None + provider_key: str | None + provider_model: str | None + bearer_auth: str | None + + websocket_base_url: str | httpx.URL | None + """Base URL for WebSocket connections. + + If not specified, the default base URL will be used, with 'wss://' replacing the + 'http://' or 'https://' scheme. For example: 'http://example.com' becomes + 'wss://example.com' + """ def __init__( self, *, api_key: str | None = None, x_api_key: str | None = None, + as_base_url: str | None = None, dedalus_org_id: str | None = None, + provider: str | None = None, + provider_key: str | None = None, + provider_model: str | None = None, + bearer_auth: str | None = None, base_url: str | httpx.URL | None = None, + websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, @@ -311,25 +399,43 @@ def __init__( This automatically infers the following arguments from their corresponding environment variables if they are not provided: - `api_key` from `DEDALUS_API_KEY` - `x_api_key` from `DEDALUS_X_API_KEY` + - `as_base_url` from `DEDALUS_AS_URL` - `dedalus_org_id` from `DEDALUS_ORG_ID` + - `provider` from `DEDALUS_PROVIDER` + - `provider_key` from `DEDALUS_PROVIDER_KEY` + - `provider_model` from `DEDALUS_PROVIDER_MODEL` """ if api_key is None: api_key = os.environ.get("DEDALUS_API_KEY") self.api_key = api_key - if x_api_key is None: x_api_key = os.environ.get("DEDALUS_X_API_KEY") self.x_api_key = x_api_key - + if as_base_url is None: + as_base_url = os.environ.get("DEDALUS_AS_URL", "").strip() or None + if as_base_url is None: + as_base_url = "https://as.dedaluslabs.ai" + self.as_base_url = as_base_url if dedalus_org_id is None: dedalus_org_id = os.environ.get("DEDALUS_ORG_ID") self.dedalus_org_id = dedalus_org_id - + if provider is None: + provider = os.environ.get("DEDALUS_PROVIDER") + self.provider = provider + if provider_key is None: + provider_key = os.environ.get("DEDALUS_PROVIDER_KEY") + self.provider_key = provider_key + if provider_model is None: + provider_model = os.environ.get("DEDALUS_PROVIDER_MODEL") + self.provider_model = provider_model + if bearer_auth is None: + bearer_auth = os.environ.get("DEDALUS_BEARER_AUTH") + self.bearer_auth = bearer_auth + self.websocket_base_url = websocket_base_url if base_url is None: base_url = os.environ.get("DEDALUS_BASE_URL") if base_url is None: - base_url = f"https://dcs.dedaluslabs.ai" - + base_url = "https://dcs.dedaluslabs.ai" custom_headers_env = os.environ.get("DEDALUS_CUSTOM_HEADERS") if custom_headers_env is not None: parsed: dict[str, str] = {} @@ -338,7 +444,6 @@ def __init__( 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, @@ -349,15 +454,27 @@ def __init__( custom_query=default_query, _strict_response_validation=_strict_response_validation, ) - self._idempotency_header = "Idempotency-Key" + self._default_stream_cls = AsyncStream @cached_property - def machines(self) -> AsyncMachinesResource: - from .resources.machines import AsyncMachinesResource - + def machines(self) -> "AsyncMachinesResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.machines import AsyncMachinesResource return AsyncMachinesResource(self) + @cached_property + def networks(self) -> "AsyncNetworksResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.networks import AsyncNetworksResource + return AsyncNetworksResource(self) + + @cached_property + def usage(self) -> "AsyncUsageResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.usage import AsyncUsageResource + return AsyncUsageResource(self) + @cached_property def with_raw_response(self) -> AsyncDedalusWithRawResponse: return AsyncDedalusWithRawResponse(self) @@ -369,53 +486,80 @@ def with_streaming_response(self) -> AsyncDedalusWithStreamedResponse: @property @override def qs(self) -> Querystring: - return Querystring(array_format="repeat") + return Querystring(array_format="comma") + @property @override - def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: - headers: dict[str, str] = {} - if security.get("api_key_auth", False): - for key, value in self._api_key_auth.items(): - headers.setdefault(key, value) - if security.get("bearer_auth", False): - for key, value in self._bearer_auth.items(): - headers.setdefault(key, value) - return headers + def auth_headers(self) -> dict[str, str]: + return { + **self._api_key_header_auth, + **self._x_api_key_header_auth, + **self._bearer_auth_header_auth, + } + + @override + def _auth_query(self, security: dict[str, bool]) -> dict[str, str]: + _ = security + return {} + + @override + def _auth_cookies(self, security: dict[str, bool]) -> dict[str, str]: + _ = security + return {} @property - def _api_key_auth(self) -> dict[str, str]: - x_api_key = self.x_api_key - if x_api_key is None: + def _api_key_header_auth(self) -> dict[str, str]: + value = self.api_key + if value is None: return {} - return {"x-api-key": x_api_key} + return {"Authorization": f"Bearer {value}"} @property - def _bearer_auth(self) -> dict[str, str]: - api_key = self.api_key - if api_key is None: + def _x_api_key_header_auth(self) -> dict[str, str]: + value = self.x_api_key + if value is None: + return {} + return {"x-api-key": value} + + @property + def _bearer_auth_header_auth(self) -> dict[str, str]: + value = self.bearer_auth + if value is None: return {} - return {"Authorization": f"Bearer {api_key}"} + return {"Authorization": f"Bearer {value}"} @property @override def default_headers(self) -> dict[str, str | Omit]: return { **super().default_headers, - "X-Stainless-Async": f"async:{get_async_library()}", - "X-Dedalus-Org-Id": self.dedalus_org_id if self.dedalus_org_id is not None else Omit(), + "X-Scalar-Async": f"async:{get_async_library()}", + "User-Agent": "Dedalus-SDK", + "X-SDK-Version": "1.0.0", + "X-Provider": self.provider if self.provider is not None else Omit(), + "X-Provider-Key": self.provider_key if self.provider_key is not None else Omit(), + "X-Provider-Model": self.provider_model if self.provider_model is not None else Omit(), **self._custom_headers, } @override - def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None: - if headers.get("x-api-key") or isinstance(custom_headers.get("x-api-key"), Omit): + def _validate_headers( + self, + headers: Headers, + custom_headers: Headers, + params: Mapping[str, object], + cookies: Mapping[str, str], + ) -> None: + if headers.get("Authorization"): return - - if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit): + if isinstance(custom_headers.get("Authorization"), Omit): + return + if headers.get("x-api-key"): + return + if isinstance(custom_headers.get("x-api-key"), Omit): return - raise TypeError( - '"Could not resolve authentication method. Expected either x_api_key or api_key to be set. Or for one of the `x-api-key` or `Authorization` headers to be explicitly omitted"' + '"Could not resolve authentication method. Expected either api_key, bearer_auth or x_api_key to be set. Or for one of the `Authorization` or `x-api-key` headers to be explicitly omitted"' ) def copy( @@ -423,7 +567,13 @@ def copy( *, api_key: str | None = None, x_api_key: str | None = None, + as_base_url: str | None = None, dedalus_org_id: str | None = None, + provider: str | None = None, + provider_key: str | None = None, + provider_model: str | None = None, + bearer_auth: str | None = None, + websocket_base_url: str | httpx.URL | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, @@ -434,74 +584,60 @@ def copy( set_default_query: Mapping[str, object] | None = None, _extra_kwargs: Mapping[str, Any] = {}, ) -> Self: - """ - Create a new client instance re-using the same options given to the current client with optional overriding. - """ + """Create a new client reusing this client's options with optional overrides.""" if default_headers is not None and set_default_headers is not None: raise ValueError("The `default_headers` and `set_default_headers` arguments are mutually exclusive") - if default_query is not None and set_default_query is not None: raise ValueError("The `default_query` and `set_default_query` arguments are mutually exclusive") - headers = self._custom_headers if default_headers is not None: headers = {**headers, **default_headers} elif set_default_headers is not None: headers = set_default_headers - params = self._custom_query if default_query is not None: params = {**params, **default_query} elif set_default_query is not None: params = set_default_query - http_client = http_client or self._client return self.__class__( api_key=api_key or self.api_key, x_api_key=x_api_key or self.x_api_key, + as_base_url=as_base_url or self.as_base_url, dedalus_org_id=dedalus_org_id or self.dedalus_org_id, + provider=provider or self.provider, + provider_key=provider_key or self.provider_key, + provider_model=provider_model or self.provider_model, + bearer_auth=bearer_auth or self.bearer_auth, + websocket_base_url=websocket_base_url or self.websocket_base_url, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, max_retries=max_retries if is_given(max_retries) else self.max_retries, default_headers=headers, default_query=params, + _strict_response_validation=self._strict_response_validation, **_extra_kwargs, ) - # Alias for `copy` for nicer inline usage, e.g. - # client.with_options(timeout=10).foo.create(...) with_options = copy @override - def _make_status_error( - self, - err_msg: str, - *, - body: object, - response: httpx.Response, - ) -> APIStatusError: + def _make_status_error(self, err_msg: str, *, body: object, response: httpx.Response) -> APIStatusError: if response.status_code == 400: return _exceptions.BadRequestError(err_msg, response=response, body=body) - if response.status_code == 401: return _exceptions.AuthenticationError(err_msg, response=response, body=body) - if response.status_code == 403: return _exceptions.PermissionDeniedError(err_msg, response=response, body=body) - if response.status_code == 404: return _exceptions.NotFoundError(err_msg, response=response, body=body) - if response.status_code == 409: return _exceptions.ConflictError(err_msg, response=response, body=body) - if response.status_code == 422: return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body) - if response.status_code == 429: return _exceptions.RateLimitError(err_msg, response=response, body=body) - if response.status_code >= 500: return _exceptions.InternalServerError(err_msg, response=response, body=body) return APIStatusError(err_msg, response=response, body=body) @@ -515,10 +651,22 @@ def __init__(self, client: Dedalus) -> None: @cached_property def machines(self) -> machines.MachinesResourceWithRawResponse: - from .resources.machines import MachinesResourceWithRawResponse - + with _RESOURCE_IMPORT_LOCK: + from .resources.machines import MachinesResourceWithRawResponse return MachinesResourceWithRawResponse(self._client.machines) + @cached_property + def networks(self) -> networks.NetworksResourceWithRawResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.networks import NetworksResourceWithRawResponse + return NetworksResourceWithRawResponse(self._client.networks) + + @cached_property + def usage(self) -> usage.UsageResourceWithRawResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.usage import UsageResourceWithRawResponse + return UsageResourceWithRawResponse(self._client.usage) + class AsyncDedalusWithRawResponse: _client: AsyncDedalus @@ -528,10 +676,22 @@ def __init__(self, client: AsyncDedalus) -> None: @cached_property def machines(self) -> machines.AsyncMachinesResourceWithRawResponse: - from .resources.machines import AsyncMachinesResourceWithRawResponse - + with _RESOURCE_IMPORT_LOCK: + from .resources.machines import AsyncMachinesResourceWithRawResponse return AsyncMachinesResourceWithRawResponse(self._client.machines) + @cached_property + def networks(self) -> networks.AsyncNetworksResourceWithRawResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.networks import AsyncNetworksResourceWithRawResponse + return AsyncNetworksResourceWithRawResponse(self._client.networks) + + @cached_property + def usage(self) -> usage.AsyncUsageResourceWithRawResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.usage import AsyncUsageResourceWithRawResponse + return AsyncUsageResourceWithRawResponse(self._client.usage) + class DedalusWithStreamedResponse: _client: Dedalus @@ -541,10 +701,22 @@ def __init__(self, client: Dedalus) -> None: @cached_property def machines(self) -> machines.MachinesResourceWithStreamingResponse: - from .resources.machines import MachinesResourceWithStreamingResponse - + with _RESOURCE_IMPORT_LOCK: + from .resources.machines import MachinesResourceWithStreamingResponse return MachinesResourceWithStreamingResponse(self._client.machines) + @cached_property + def networks(self) -> networks.NetworksResourceWithStreamingResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.networks import NetworksResourceWithStreamingResponse + return NetworksResourceWithStreamingResponse(self._client.networks) + + @cached_property + def usage(self) -> usage.UsageResourceWithStreamingResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.usage import UsageResourceWithStreamingResponse + return UsageResourceWithStreamingResponse(self._client.usage) + class AsyncDedalusWithStreamedResponse: _client: AsyncDedalus @@ -554,11 +726,23 @@ def __init__(self, client: AsyncDedalus) -> None: @cached_property def machines(self) -> machines.AsyncMachinesResourceWithStreamingResponse: - from .resources.machines import AsyncMachinesResourceWithStreamingResponse - + with _RESOURCE_IMPORT_LOCK: + from .resources.machines import AsyncMachinesResourceWithStreamingResponse return AsyncMachinesResourceWithStreamingResponse(self._client.machines) + @cached_property + def networks(self) -> networks.AsyncNetworksResourceWithStreamingResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.networks import AsyncNetworksResourceWithStreamingResponse + return AsyncNetworksResourceWithStreamingResponse(self._client.networks) + + @cached_property + def usage(self) -> usage.AsyncUsageResourceWithStreamingResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.usage import AsyncUsageResourceWithStreamingResponse + return AsyncUsageResourceWithStreamingResponse(self._client.usage) -Client = Dedalus +# Alias names for the documented `Client` / `AsyncClient` symbols. +Client = Dedalus AsyncClient = AsyncDedalus diff --git a/src/dedalus_sdk/_constants.py b/src/dedalus_sdk/_constants.py index 6ddf2c7..969d075 100644 --- a/src/dedalus_sdk/_constants.py +++ b/src/dedalus_sdk/_constants.py @@ -1,9 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See CONTRIBUTING.md for details. import httpx -RAW_RESPONSE_HEADER = "X-Stainless-Raw-Response" -OVERRIDE_CAST_TO_HEADER = "____stainless_override_cast_to" +RAW_RESPONSE_HEADER = "X-Scalar-Raw-Response" +OVERRIDE_CAST_TO_HEADER = "____scalar_override_cast_to" # default timeout is 1 minute DEFAULT_TIMEOUT = httpx.Timeout(timeout=60, connect=5.0) diff --git a/src/dedalus_sdk/_event_handler.py b/src/dedalus_sdk/_event_handler.py new file mode 100644 index 0000000..d84a24d --- /dev/null +++ b/src/dedalus_sdk/_event_handler.py @@ -0,0 +1,85 @@ +# File generated from our OpenAPI spec by Scalar. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import threading +from typing import Any, Callable + +EventHandler = Callable[..., Any] + + +class EventHandlerRegistry: + """Thread-safe (optional) registry of event handlers.""" + + def __init__(self, *, use_lock: bool = False) -> None: + self._handlers: dict[str, list[EventHandler]] = {} + self._once_ids: set[int] = set() + self._lock: threading.Lock | None = threading.Lock() if use_lock else None + + def _acquire(self) -> None: + if self._lock is not None: + self._lock.acquire() + + def _release(self) -> None: + if self._lock is not None: + self._lock.release() + + def add(self, event_type: str, handler: EventHandler, *, once: bool = False) -> None: + self._acquire() + try: + handlers = self._handlers.setdefault(event_type, []) + handlers.append(handler) + if once: + self._once_ids.add(id(handler)) + finally: + self._release() + + def remove(self, event_type: str, handler: EventHandler) -> None: + self._acquire() + try: + handlers = self._handlers.get(event_type) + if handlers is not None: + try: + handlers.remove(handler) + except ValueError: + pass + self._once_ids.discard(id(handler)) + finally: + self._release() + + def get_handlers(self, event_type: str) -> list[EventHandler]: + """Return a snapshot of handlers for the given event type, removing once-handlers.""" + self._acquire() + try: + handlers = self._handlers.get(event_type) + if not handlers: + return [] + result = list(handlers) + to_remove = [h for h in result if id(h) in self._once_ids] + for h in to_remove: + handlers.remove(h) + self._once_ids.discard(id(h)) + return result + finally: + self._release() + + def has_handlers(self, event_type: str) -> bool: + self._acquire() + try: + handlers = self._handlers.get(event_type) + return bool(handlers) + finally: + self._release() + + def merge_into(self, target: EventHandlerRegistry) -> None: + """Move all handlers from this registry into *target*, then clear self.""" + self._acquire() + try: + for event_type, handlers in self._handlers.items(): + for handler in handlers: + once = id(handler) in self._once_ids + target.add(event_type, handler, once=once) + self._handlers.clear() + self._once_ids.clear() + finally: + self._release() diff --git a/src/dedalus_sdk/_exceptions.py b/src/dedalus_sdk/_exceptions.py index b1b6b06..696928f 100644 --- a/src/dedalus_sdk/_exceptions.py +++ b/src/dedalus_sdk/_exceptions.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See CONTRIBUTING.md for details. from __future__ import annotations @@ -15,6 +15,8 @@ "UnprocessableEntityError", "RateLimitError", "InternalServerError", + "WebSocketConnectionClosedError", + "WebSocketQueueFullError", ] @@ -106,3 +108,19 @@ class RateLimitError(APIStatusError): class InternalServerError(APIStatusError): pass + + +class WebSocketConnectionClosedError(DedalusError): + """Raised when a WebSocket connection closes with unsent messages.""" + + unsent_messages: list[str] + + def __init__(self, message: str, *, unsent_messages: list[str]) -> None: + super().__init__(message) + self.unsent_messages = unsent_messages + + +class WebSocketQueueFullError(DedalusError): + """Raised when the outgoing WebSocket message queue exceeds its byte-size limit.""" + + pass diff --git a/src/dedalus_sdk/_resource.py b/src/dedalus_sdk/_resource.py index 390620d..8512f4b 100644 --- a/src/dedalus_sdk/_resource.py +++ b/src/dedalus_sdk/_resource.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See CONTRIBUTING.md for details. from __future__ import annotations diff --git a/src/dedalus_sdk/_response.py b/src/dedalus_sdk/_response.py index 22dc619..6881775 100644 --- a/src/dedalus_sdk/_response.py +++ b/src/dedalus_sdk/_response.py @@ -25,7 +25,14 @@ import pydantic from ._types import NoneType -from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base +from ._utils import ( + is_given, + is_union_type, + extract_type_arg, + is_annotated_type, + is_type_alias_type, + extract_type_var_from_base, +) from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type @@ -181,7 +188,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: ), ) - if cast_to is NoneType: + if cast_to is None or cast_to is NoneType: return cast(R, None) response = self.http_response @@ -228,8 +235,8 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: cast_to is not object and not origin is list and not origin is dict - and not origin is Union - and not issubclass(origin, BaseModel) + and not is_union_type(cast_to) + and not (inspect.isclass(origin) and issubclass(origin, BaseModel)) ): raise RuntimeError( f"Unsupported type, expected {cast_to} to be a subclass of {BaseModel}, {dict}, {list}, {Union}, {NoneType}, {str} or {httpx.Response}." diff --git a/src/dedalus_sdk/_send_queue.py b/src/dedalus_sdk/_send_queue.py new file mode 100644 index 0000000..3140d45 --- /dev/null +++ b/src/dedalus_sdk/_send_queue.py @@ -0,0 +1,90 @@ +# File generated from our OpenAPI spec by Scalar. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import typing +import threading + +from ._exceptions import WebSocketQueueFullError + + +class SendQueue: + """Bounded byte-size queue for outgoing WebSocket messages. + + Messages are stored as pre-serialized strings. The queue enforces a + maximum byte budget so that unbounded buffering cannot occur during + reconnection windows. + """ + + def __init__(self, max_bytes: int = 1_048_576) -> None: + self._queue: list[tuple[str, int]] = [] # (data, byte_length) + self._bytes: int = 0 + self._max_bytes = max_bytes + self._lock = threading.Lock() + + def enqueue(self, data: str) -> None: + """Append *data* to the queue. + + Raises :class:`WebSocketQueueFullError` if the message would + exceed the byte-size limit. + """ + byte_length = len(data.encode("utf-8")) + with self._lock: + if self._bytes + byte_length > self._max_bytes: + raise WebSocketQueueFullError("send queue is full, message discarded") + self._queue.append((data, byte_length)) + self._bytes += byte_length + + def flush_sync(self, send: typing.Callable[[str], object]) -> None: + """Send every queued message via *send*. + + If *send* raises, the failing message and all subsequent messages + are re-queued and the error is re-raised. + """ + with self._lock: + pending = list(self._queue) + self._queue.clear() + self._bytes = 0 + + for i, (data, _byte_length) in enumerate(pending): + try: + send(data) + except Exception: + with self._lock: + remaining = pending[i:] + self._queue = remaining + self._queue + self._bytes = sum(bl for _, bl in self._queue) + raise + + async def flush_async(self, send: typing.Callable[[str], typing.Awaitable[object]]) -> None: + """Async variant of :meth:`flush_sync`.""" + with self._lock: + pending = list(self._queue) + self._queue.clear() + self._bytes = 0 + + for i, (data, _byte_length) in enumerate(pending): + try: + await send(data) + except Exception: + with self._lock: + remaining = pending[i:] + self._queue = remaining + self._queue + self._bytes = sum(bl for _, bl in self._queue) + raise + + def drain(self) -> list[str]: + """Remove and return all queued messages.""" + with self._lock: + items = [data for data, _ in self._queue] + self._queue.clear() + self._bytes = 0 + return items + + def __len__(self) -> int: + with self._lock: + return len(self._queue) + + def __bool__(self) -> bool: + with self._lock: + return len(self._queue) > 0 diff --git a/src/dedalus_sdk/_streaming.py b/src/dedalus_sdk/_streaming.py index d71126c..e759a64 100644 --- a/src/dedalus_sdk/_streaming.py +++ b/src/dedalus_sdk/_streaming.py @@ -59,7 +59,23 @@ def __stream__(self) -> Iterator[_T]: try: for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) + if sse.event == "error": + body = sse.data + + try: + body = sse.json() + err_msg = f"{body}" + except Exception: + err_msg = sse.data or f"Error code: {response.status_code}" + + raise self._client._make_status_error( + err_msg, + body=body, + response=self.response, + ) + + if True: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) finally: # Ensure the response is closed even if the consumer doesn't read all data response.close() @@ -125,7 +141,23 @@ async def __stream__(self) -> AsyncIterator[_T]: try: async for sse in iterator: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) + if sse.event == "error": + body = sse.data + + try: + body = sse.json() + err_msg = f"{body}" + except Exception: + err_msg = sse.data or f"Error code: {response.status_code}" + + raise self._client._make_status_error( + err_msg, + body=body, + response=self.response, + ) + + if True: + yield process_data(data=sse.json(), cast_to=cast_to, response=response) finally: # Ensure the response is closed even if the consumer doesn't read all data await response.aclose() diff --git a/src/dedalus_sdk/_utils/_utils.py b/src/dedalus_sdk/_utils/_utils.py index 199cd23..8b051e2 100644 --- a/src/dedalus_sdk/_utils/_utils.py +++ b/src/dedalus_sdk/_utils/_utils.py @@ -389,7 +389,7 @@ def get_required_header(headers: HeadersLike, header: str) -> str: if k.lower() == lower_header and isinstance(v, str): return v - # to deal with the case where the header looks like Stainless-Event-Id + # to deal with the case where the header looks like Scalar-Event-Id intercaps_header = re.sub(r"([^\w])(\w)", lambda pat: pat.group(1) + pat.group(2).upper(), header.capitalize()) for normalized_header in [header, lower_header, header.upper(), intercaps_header]: diff --git a/src/dedalus_sdk/_version.py b/src/dedalus_sdk/_version.py index 2e5e834..6686d0b 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. +# File generated from our OpenAPI spec by Scalar. See README.md for details. -__title__ = "dedalus_sdk" +__title__ = "dedalus" __version__ = "0.5.0" # x-release-please-version diff --git a/src/dedalus_sdk/lib/.keep b/src/dedalus_sdk/lib/.keep deleted file mode 100644 index 5e2c99f..0000000 --- a/src/dedalus_sdk/lib/.keep +++ /dev/null @@ -1,4 +0,0 @@ -File generated from our OpenAPI spec by Stainless. - -This directory can be used to store custom files to expand the SDK. -It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/dedalus_sdk/pagination.py b/src/dedalus_sdk/pagination.py index 622bf83..34bb81c 100644 --- a/src/dedalus_sdk/pagination.py +++ b/src/dedalus_sdk/pagination.py @@ -1,15 +1,30 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See CONTRIBUTING.md for details. -from typing import List, Generic, TypeVar, Optional +from typing import List, Generic, TypeVar, Optional, cast from typing_extensions import override + from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage +from ._models import construct_type __all__ = ["SyncCursorPage", "AsyncCursorPage"] _T = TypeVar("_T") +def _has_next_cursor(cursor: object) -> bool: + """Return True for non-empty string cursors and finite numeric cursor IDs like 0.""" + import math + + if isinstance(cursor, bool): + return False + if isinstance(cursor, str): + return cursor != "" + if isinstance(cursor, (int, float)): + return math.isfinite(cursor) + return False + + class SyncCursorPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): items: List[_T] next_cursor: Optional[str] = None @@ -19,15 +34,16 @@ def _get_page_items(self) -> List[_T]: items = self.items if not items: return [] - return items + # The item model is attached by the response post-parser after the page is parsed. + return [cast(_T, construct_type(value=item, type_=self._model)) for item in items] @override def next_page_info(self) -> Optional[PageInfo]: - next_cursor = self.next_cursor - if not next_cursor: + cursor = self.next_cursor + if not _has_next_cursor(cursor): return None - return PageInfo(params={"cursor": next_cursor}) + return PageInfo(params={"cursor": cursor}) class AsyncCursorPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): @@ -39,12 +55,13 @@ def _get_page_items(self) -> List[_T]: items = self.items if not items: return [] - return items + # The item model is attached by the response post-parser after the page is parsed. + return [cast(_T, construct_type(value=item, type_=self._model)) for item in items] @override def next_page_info(self) -> Optional[PageInfo]: - next_cursor = self.next_cursor - if not next_cursor: + cursor = self.next_cursor + if not _has_next_cursor(cursor): return None - return PageInfo(params={"cursor": next_cursor}) + return PageInfo(params={"cursor": cursor}) diff --git a/src/dedalus_sdk/resources/__init__.py b/src/dedalus_sdk/resources/__init__.py index 2967015..f20d857 100644 --- a/src/dedalus_sdk/resources/__init__.py +++ b/src/dedalus_sdk/resources/__init__.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from .machines import ( MachinesResource, @@ -8,6 +8,22 @@ MachinesResourceWithStreamingResponse, AsyncMachinesResourceWithStreamingResponse, ) +from .networks import ( + NetworksResource, + AsyncNetworksResource, + NetworksResourceWithRawResponse, + AsyncNetworksResourceWithRawResponse, + NetworksResourceWithStreamingResponse, + AsyncNetworksResourceWithStreamingResponse, +) +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) __all__ = [ "MachinesResource", @@ -16,4 +32,16 @@ "AsyncMachinesResourceWithRawResponse", "MachinesResourceWithStreamingResponse", "AsyncMachinesResourceWithStreamingResponse", + "NetworksResource", + "AsyncNetworksResource", + "NetworksResourceWithRawResponse", + "AsyncNetworksResourceWithRawResponse", + "NetworksResourceWithStreamingResponse", + "AsyncNetworksResourceWithStreamingResponse", + "UsageResource", + "AsyncUsageResource", + "UsageResourceWithRawResponse", + "AsyncUsageResourceWithRawResponse", + "UsageResourceWithStreamingResponse", + "AsyncUsageResourceWithStreamingResponse", ] diff --git a/src/dedalus_sdk/resources/machines/__init__.py b/src/dedalus_sdk/resources/machines/__init__.py index dfb0fcf..da88c79 100644 --- a/src/dedalus_sdk/resources/machines/__init__.py +++ b/src/dedalus_sdk/resources/machines/__init__.py @@ -1,13 +1,5 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. -from .ssh import ( - SSHResource, - AsyncSSHResource, - SSHResourceWithRawResponse, - AsyncSSHResourceWithRawResponse, - SSHResourceWithStreamingResponse, - AsyncSSHResourceWithStreamingResponse, -) from .machines import ( MachinesResource, AsyncMachinesResource, @@ -16,6 +8,38 @@ MachinesResourceWithStreamingResponse, AsyncMachinesResourceWithStreamingResponse, ) +from .network import ( + NetworkResource, + AsyncNetworkResource, + NetworkResourceWithRawResponse, + AsyncNetworkResourceWithRawResponse, + NetworkResourceWithStreamingResponse, + AsyncNetworkResourceWithStreamingResponse, +) +from .artifacts import ( + ArtifactsResource, + AsyncArtifactsResource, + ArtifactsResourceWithRawResponse, + AsyncArtifactsResourceWithRawResponse, + ArtifactsResourceWithStreamingResponse, + AsyncArtifactsResourceWithStreamingResponse, +) +from .ports import ( + PortsResource, + AsyncPortsResource, + PortsResourceWithRawResponse, + AsyncPortsResourceWithRawResponse, + PortsResourceWithStreamingResponse, + AsyncPortsResourceWithStreamingResponse, +) +from .ssh import ( + SSHResource, + AsyncSSHResource, + SSHResourceWithRawResponse, + AsyncSSHResourceWithRawResponse, + SSHResourceWithStreamingResponse, + AsyncSSHResourceWithStreamingResponse, +) from .executions import ( ExecutionsResource, AsyncExecutionsResource, @@ -24,8 +48,40 @@ ExecutionsResourceWithStreamingResponse, AsyncExecutionsResourceWithStreamingResponse, ) +from .terminals import ( + TerminalsResource, + AsyncTerminalsResource, + TerminalsResourceWithRawResponse, + AsyncTerminalsResourceWithRawResponse, + TerminalsResourceWithStreamingResponse, + AsyncTerminalsResourceWithStreamingResponse, +) __all__ = [ + "MachinesResource", + "AsyncMachinesResource", + "MachinesResourceWithRawResponse", + "AsyncMachinesResourceWithRawResponse", + "MachinesResourceWithStreamingResponse", + "AsyncMachinesResourceWithStreamingResponse", + "NetworkResource", + "AsyncNetworkResource", + "NetworkResourceWithRawResponse", + "AsyncNetworkResourceWithRawResponse", + "NetworkResourceWithStreamingResponse", + "AsyncNetworkResourceWithStreamingResponse", + "ArtifactsResource", + "AsyncArtifactsResource", + "ArtifactsResourceWithRawResponse", + "AsyncArtifactsResourceWithRawResponse", + "ArtifactsResourceWithStreamingResponse", + "AsyncArtifactsResourceWithStreamingResponse", + "PortsResource", + "AsyncPortsResource", + "PortsResourceWithRawResponse", + "AsyncPortsResourceWithRawResponse", + "PortsResourceWithStreamingResponse", + "AsyncPortsResourceWithStreamingResponse", "SSHResource", "AsyncSSHResource", "SSHResourceWithRawResponse", @@ -38,10 +94,10 @@ "AsyncExecutionsResourceWithRawResponse", "ExecutionsResourceWithStreamingResponse", "AsyncExecutionsResourceWithStreamingResponse", - "MachinesResource", - "AsyncMachinesResource", - "MachinesResourceWithRawResponse", - "AsyncMachinesResourceWithRawResponse", - "MachinesResourceWithStreamingResponse", - "AsyncMachinesResourceWithStreamingResponse", + "TerminalsResource", + "AsyncTerminalsResource", + "TerminalsResourceWithRawResponse", + "AsyncTerminalsResourceWithRawResponse", + "TerminalsResourceWithStreamingResponse", + "AsyncTerminalsResourceWithStreamingResponse", ] diff --git a/src/dedalus_sdk/resources/machines/artifacts.py b/src/dedalus_sdk/resources/machines/artifacts.py new file mode 100644 index 0000000..c499710 --- /dev/null +++ b/src/dedalus_sdk/resources/machines/artifacts.py @@ -0,0 +1,432 @@ +# File generated from our OpenAPI spec by Scalar. See README.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, strip_not_given +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...pagination import SyncCursorPage, AsyncCursorPage +from ..._base_client import AsyncPaginator, make_request_options +from ...types.machines import artifact_list_params +from ...types.machines.artifact import Artifact + +__all__ = ["ArtifactsResource", "AsyncArtifactsResource"] + + +class ArtifactsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ArtifactsResourceWithRawResponse: + return ArtifactsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ArtifactsResourceWithStreamingResponse: + return ArtifactsResourceWithStreamingResponse(self) + + def list( + self, + *, + machine_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> SyncCursorPage[Artifact]: + """ + List artifacts + + Args: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SyncCursorPage[Artifact]: OK + + Example: + ```python + page = client.machines.artifacts.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/artifacts", **{"machine_id": machine_id}), + page=SyncCursorPage[Artifact], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, artifact_list_params.ArtifactListParams), + ), + model=Artifact, + method="get", + ) + + def retrieve( + self, + *, + machine_id: str, + artifact_id: str, + x_dedalus_org_id: 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, + ) -> Artifact: + """ + Get artifact + + Args: + machine_id: Path parameter. + artifact_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Artifact: OK + + Example: + ```python + artifact = client.machines.artifacts.retrieve( + machine_id="machineID", + artifact_id="artifactID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): + raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get( + path_template( + "/v1/machines/{machine_id}/artifacts/{artifact_id}", + **{"machine_id": machine_id, "artifact_id": artifact_id}, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Artifact, + ) + + def delete( + self, + *, + machine_id: str, + artifact_id: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Artifact: + """ + Delete artifact + + Args: + machine_id: Path parameter. + artifact_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Artifact: OK + + Example: + ```python + artifact = client.machines.artifacts.delete( + machine_id="machineID", + artifact_id="artifactID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): + raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._delete( + path_template( + "/v1/machines/{machine_id}/artifacts/{artifact_id}", + **{"machine_id": machine_id, "artifact_id": artifact_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Artifact, + ) + + +class AsyncArtifactsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncArtifactsResourceWithRawResponse: + return AsyncArtifactsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncArtifactsResourceWithStreamingResponse: + return AsyncArtifactsResourceWithStreamingResponse(self) + + def list( + self, + *, + machine_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> AsyncPaginator[Artifact, AsyncCursorPage[Artifact]]: + """ + List artifacts + + Args: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncPaginator[Artifact, AsyncCursorPage[Artifact]]: OK + + Example: + ```python + page = client.machines.artifacts.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/artifacts", **{"machine_id": machine_id}), + page=AsyncCursorPage[Artifact], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, artifact_list_params.ArtifactListParams), + ), + model=Artifact, + method="get", + ) + + async def retrieve( + self, + *, + machine_id: str, + artifact_id: str, + x_dedalus_org_id: 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, + ) -> Artifact: + """ + Get artifact + + Args: + machine_id: Path parameter. + artifact_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Artifact: OK + + Example: + ```python + artifact = await client.machines.artifacts.retrieve( + machine_id="machineID", + artifact_id="artifactID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): + raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._get( + path_template( + "/v1/machines/{machine_id}/artifacts/{artifact_id}", + **{"machine_id": machine_id, "artifact_id": artifact_id}, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Artifact, + ) + + async def delete( + self, + *, + machine_id: str, + artifact_id: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Artifact: + """ + Delete artifact + + Args: + machine_id: Path parameter. + artifact_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Artifact: OK + + Example: + ```python + artifact = await client.machines.artifacts.delete( + machine_id="machineID", + artifact_id="artifactID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): + raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._delete( + path_template( + "/v1/machines/{machine_id}/artifacts/{artifact_id}", + **{"machine_id": machine_id, "artifact_id": artifact_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Artifact, + ) + + +class ArtifactsResourceWithRawResponse: + def __init__(self, artifacts: ArtifactsResource) -> None: + self._artifacts = artifacts + + self.list = to_raw_response_wrapper( + artifacts.list, + ) + self.retrieve = to_raw_response_wrapper( + artifacts.retrieve, + ) + self.delete = to_raw_response_wrapper( + artifacts.delete, + ) + + +class AsyncArtifactsResourceWithRawResponse: + def __init__(self, artifacts: AsyncArtifactsResource) -> None: + self._artifacts = artifacts + + self.list = async_to_raw_response_wrapper( + artifacts.list, + ) + self.retrieve = async_to_raw_response_wrapper( + artifacts.retrieve, + ) + self.delete = async_to_raw_response_wrapper( + artifacts.delete, + ) + + +class ArtifactsResourceWithStreamingResponse: + def __init__(self, artifacts: ArtifactsResource) -> None: + self._artifacts = artifacts + + self.list = to_streamed_response_wrapper( + artifacts.list, + ) + self.retrieve = to_streamed_response_wrapper( + artifacts.retrieve, + ) + self.delete = to_streamed_response_wrapper( + artifacts.delete, + ) + + +class AsyncArtifactsResourceWithStreamingResponse: + def __init__(self, artifacts: AsyncArtifactsResource) -> None: + self._artifacts = artifacts + + self.list = async_to_streamed_response_wrapper( + artifacts.list, + ) + self.retrieve = async_to_streamed_response_wrapper( + artifacts.retrieve, + ) + self.delete = async_to_streamed_response_wrapper( + artifacts.delete, + ) diff --git a/src/dedalus_sdk/resources/machines/executions.py b/src/dedalus_sdk/resources/machines/executions.py index bd2a80e..36d1b8b 100644 --- a/src/dedalus_sdk/resources/machines/executions.py +++ b/src/dedalus_sdk/resources/machines/executions.py @@ -1,13 +1,14 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing import Dict, Optional - import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform +from typing import Dict, Optional +from ..._types import SequenceNotStr + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform, strip_not_given from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -20,8 +21,8 @@ from ..._base_client import AsyncPaginator, make_request_options from ...types.machines import execution_list_params, execution_create_params, execution_events_params from ...types.machines.execution import Execution -from ...types.machines.execution_event import ExecutionEvent from ...types.machines.execution_output import ExecutionOutput +from ...types.machines.execution_event import ExecutionEvent __all__ = ["ExecutionsResource", "AsyncExecutionsResource"] @@ -29,22 +30,65 @@ class ExecutionsResource(SyncAPIResource): @cached_property def with_raw_response(self) -> ExecutionsResourceWithRawResponse: - """ - 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 ExecutionsResourceWithRawResponse(self) @cached_property def with_streaming_response(self) -> ExecutionsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. + return ExecutionsResourceWithStreamingResponse(self) - For more information, see https://www.github.com/dedalus-labs/dedalus-python#with_streaming_response + def list( + self, + *, + machine_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> SyncCursorPage[Execution]: """ - return ExecutionsResourceWithStreamingResponse(self) + List executions + + Args: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SyncCursorPage[Execution]: OK + + Example: + ```python + page = client.machines.executions.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), + page=SyncCursorPage[Execution], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, execution_list_params.ExecutionListParams), + ), + model=Execution, + method="get", + ) def create( self, @@ -55,6 +99,7 @@ def create( env: Dict[str, str] | Omit = omit, stdin: str | Omit = omit, timeout_ms: int | Omit = omit, + x_dedalus_org_id: 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, @@ -67,20 +112,36 @@ def create( Create execution Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not machine_id: + machine_id: Path parameter. + command: Body parameter. + cwd: Body parameter. + env: Body parameter. + stdin: Body parameter. + timeout_ms: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Execution: OK + + Example: + ```python + execution = client.machines.executions.create( + machine_id="machineID", + command=[""], + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( - path_template("/v1/machines/{machine_id}/executions", machine_id=machine_id), + path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), body=maybe_transform( { "command": command, @@ -106,6 +167,7 @@ def retrieve( *, machine_id: str, execution_id: str, + x_dedalus_org_id: 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, @@ -117,21 +179,34 @@ def retrieve( Get execution Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Execution: OK + + Example: + ```python + execution = client.machines.executions.retrieve( + machine_id="machineID", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: + if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get( path_template( - "/v1/machines/{machine_id}/executions/{execution_id}", machine_id=machine_id, execution_id=execution_id + "/v1/machines/{machine_id}/executions/{execution_id}", + **{"machine_id": machine_id, "execution_id": execution_id}, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -139,95 +214,115 @@ def retrieve( cast_to=Execution, ) - def list( + def delete( self, *, machine_id: str, - cursor: str | Omit = omit, - limit: int | Omit = omit, + execution_id: str, + x_dedalus_org_id: 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, - ) -> SyncCursorPage[Execution]: + idempotency_key: str | None = None, + ) -> Execution: """ - List executions + Delete execution Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Execution: OK + + Example: + ```python + execution = client.machines.executions.delete( + machine_id="machineID", + execution_id="executionID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return self._get_api_list( - path_template("/v1/machines/{machine_id}/executions", machine_id=machine_id), - page=SyncCursorPage[Execution], + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._delete( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - execution_list_params.ExecutionListParams, - ), + idempotency_key=idempotency_key, ), - model=Execution, + cast_to=Execution, ) - def delete( + def output( self, *, machine_id: str, execution_id: str, + x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Execution: + ) -> ExecutionOutput: """ - Delete execution + Get execution output Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + ExecutionOutput: OK + + Example: + ```python + execution = client.machines.executions.output( + machine_id="machineID", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: + if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - return self._delete( + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get( path_template( - "/v1/machines/{machine_id}/executions/{execution_id}", machine_id=machine_id, execution_id=execution_id + "/v1/machines/{machine_id}/executions/{execution_id}/output", + **{"machine_id": machine_id, "execution_id": execution_id}, ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=Execution, + cast_to=ExecutionOutput, ) def events( @@ -235,8 +330,9 @@ def events( *, machine_id: str, execution_id: str, - cursor: str | Omit = omit, limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, @@ -248,23 +344,36 @@ def events( List execution events Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SyncCursorPage[ExecutionEvent]: OK + + Example: + ```python + page = client.machines.executions.events( + machine_id="machineID", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: + if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template( "/v1/machines/{machine_id}/executions/{execution_id}/events", - machine_id=machine_id, - execution_id=execution_id, + **{"machine_id": machine_id, "execution_id": execution_id}, ), page=SyncCursorPage[ExecutionEvent], options=make_request_options( @@ -273,77 +382,77 @@ def events( extra_body=extra_body, timeout=timeout, query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - execution_events_params.ExecutionEventsParams, + {"limit": limit, "cursor": cursor}, execution_events_params.ExecutionEventsParams ), ), model=ExecutionEvent, + method="get", ) - def output( + +class AsyncExecutionsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncExecutionsResourceWithRawResponse: + return AsyncExecutionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncExecutionsResourceWithStreamingResponse: + return AsyncExecutionsResourceWithStreamingResponse(self) + + def list( self, *, machine_id: str, - execution_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, - ) -> ExecutionOutput: + ) -> AsyncPaginator[Execution, AsyncCursorPage[Execution]]: """ - Get execution output + List executions Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncPaginator[Execution, AsyncCursorPage[Execution]]: OK + + Example: + ```python + page = client.machines.executions.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: - raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - return self._get( - path_template( - "/v1/machines/{machine_id}/executions/{execution_id}/output", - machine_id=machine_id, - execution_id=execution_id, - ), + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), + page=AsyncCursorPage[Execution], options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, execution_list_params.ExecutionListParams), ), - cast_to=ExecutionOutput, + model=Execution, + method="get", ) - -class AsyncExecutionsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncExecutionsResourceWithRawResponse: - """ - 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 AsyncExecutionsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncExecutionsResourceWithStreamingResponse: - """ - 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 AsyncExecutionsResourceWithStreamingResponse(self) - async def create( self, *, @@ -353,6 +462,7 @@ async def create( env: Dict[str, str] | Omit = omit, stdin: str | Omit = omit, timeout_ms: int | Omit = omit, + x_dedalus_org_id: 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, @@ -365,20 +475,36 @@ async def create( Create execution Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not machine_id: + machine_id: Path parameter. + command: Body parameter. + cwd: Body parameter. + env: Body parameter. + stdin: Body parameter. + timeout_ms: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Execution: OK + + Example: + ```python + execution = await client.machines.executions.create( + machine_id="machineID", + command=[""], + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( - path_template("/v1/machines/{machine_id}/executions", machine_id=machine_id), + path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), body=await async_maybe_transform( { "command": command, @@ -404,6 +530,7 @@ async def retrieve( *, machine_id: str, execution_id: str, + x_dedalus_org_id: 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, @@ -415,21 +542,34 @@ async def retrieve( Get execution Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Execution: OK + + Example: + ```python + execution = await client.machines.executions.retrieve( + machine_id="machineID", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: + if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._get( path_template( - "/v1/machines/{machine_id}/executions/{execution_id}", machine_id=machine_id, execution_id=execution_id + "/v1/machines/{machine_id}/executions/{execution_id}", + **{"machine_id": machine_id, "execution_id": execution_id}, ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout @@ -437,95 +577,115 @@ async def retrieve( cast_to=Execution, ) - def list( + async def delete( self, *, machine_id: str, - cursor: str | Omit = omit, - limit: int | Omit = omit, + execution_id: str, + x_dedalus_org_id: 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, - ) -> AsyncPaginator[Execution, AsyncCursorPage[Execution]]: + idempotency_key: str | None = None, + ) -> Execution: """ - List executions + Delete execution Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Execution: OK + + Example: + ```python + execution = await client.machines.executions.delete( + machine_id="machineID", + execution_id="executionID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return self._get_api_list( - path_template("/v1/machines/{machine_id}/executions", machine_id=machine_id), - page=AsyncCursorPage[Execution], + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._delete( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - execution_list_params.ExecutionListParams, - ), + idempotency_key=idempotency_key, ), - model=Execution, + cast_to=Execution, ) - async def delete( + async def output( self, *, machine_id: str, execution_id: str, + x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Execution: + ) -> ExecutionOutput: """ - Delete execution + Get execution output Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + ExecutionOutput: OK + + Example: + ```python + execution = await client.machines.executions.output( + machine_id="machineID", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: + if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - return await self._delete( + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._get( path_template( - "/v1/machines/{machine_id}/executions/{execution_id}", machine_id=machine_id, execution_id=execution_id + "/v1/machines/{machine_id}/executions/{execution_id}/output", + **{"machine_id": machine_id, "execution_id": execution_id}, ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=Execution, + cast_to=ExecutionOutput, ) def events( @@ -533,8 +693,9 @@ def events( *, machine_id: str, execution_id: str, - cursor: str | Omit = omit, limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, @@ -546,23 +707,36 @@ def events( List execution events Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: + machine_id: Path parameter. + execution_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncPaginator[ExecutionEvent, AsyncCursorPage[ExecutionEvent]]: OK + + Example: + ```python + page = client.machines.executions.events( + machine_id="machineID", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: + if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template( "/v1/machines/{machine_id}/executions/{execution_id}/events", - machine_id=machine_id, - execution_id=execution_id, + **{"machine_id": machine_id, "execution_id": execution_id}, ), page=AsyncCursorPage[ExecutionEvent], options=make_request_options( @@ -571,54 +745,11 @@ def events( extra_body=extra_body, timeout=timeout, query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - execution_events_params.ExecutionEventsParams, + {"limit": limit, "cursor": cursor}, execution_events_params.ExecutionEventsParams ), ), model=ExecutionEvent, - ) - - async def output( - self, - *, - machine_id: str, - execution_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ExecutionOutput: - """ - Get execution output - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not machine_id: - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not execution_id: - raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - return await self._get( - path_template( - "/v1/machines/{machine_id}/executions/{execution_id}/output", - machine_id=machine_id, - execution_id=execution_id, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ExecutionOutput, + method="get", ) @@ -626,93 +757,93 @@ class ExecutionsResourceWithRawResponse: def __init__(self, executions: ExecutionsResource) -> None: self._executions = executions + self.list = to_raw_response_wrapper( + executions.list, + ) self.create = to_raw_response_wrapper( executions.create, ) self.retrieve = to_raw_response_wrapper( executions.retrieve, ) - self.list = to_raw_response_wrapper( - executions.list, - ) self.delete = to_raw_response_wrapper( executions.delete, ) - self.events = to_raw_response_wrapper( - executions.events, - ) self.output = to_raw_response_wrapper( executions.output, ) + self.events = to_raw_response_wrapper( + executions.events, + ) class AsyncExecutionsResourceWithRawResponse: def __init__(self, executions: AsyncExecutionsResource) -> None: self._executions = executions + self.list = async_to_raw_response_wrapper( + executions.list, + ) self.create = async_to_raw_response_wrapper( executions.create, ) self.retrieve = async_to_raw_response_wrapper( executions.retrieve, ) - self.list = async_to_raw_response_wrapper( - executions.list, - ) self.delete = async_to_raw_response_wrapper( executions.delete, ) - self.events = async_to_raw_response_wrapper( - executions.events, - ) self.output = async_to_raw_response_wrapper( executions.output, ) + self.events = async_to_raw_response_wrapper( + executions.events, + ) class ExecutionsResourceWithStreamingResponse: def __init__(self, executions: ExecutionsResource) -> None: self._executions = executions + self.list = to_streamed_response_wrapper( + executions.list, + ) self.create = to_streamed_response_wrapper( executions.create, ) self.retrieve = to_streamed_response_wrapper( executions.retrieve, ) - self.list = to_streamed_response_wrapper( - executions.list, - ) self.delete = to_streamed_response_wrapper( executions.delete, ) - self.events = to_streamed_response_wrapper( - executions.events, - ) self.output = to_streamed_response_wrapper( executions.output, ) + self.events = to_streamed_response_wrapper( + executions.events, + ) class AsyncExecutionsResourceWithStreamingResponse: def __init__(self, executions: AsyncExecutionsResource) -> None: self._executions = executions + self.list = async_to_streamed_response_wrapper( + executions.list, + ) self.create = async_to_streamed_response_wrapper( executions.create, ) self.retrieve = async_to_streamed_response_wrapper( executions.retrieve, ) - self.list = async_to_streamed_response_wrapper( - executions.list, - ) self.delete = async_to_streamed_response_wrapper( executions.delete, ) - self.events = async_to_streamed_response_wrapper( - executions.events, - ) self.output = async_to_streamed_response_wrapper( executions.output, ) + self.events = async_to_streamed_response_wrapper( + executions.events, + ) diff --git a/src/dedalus_sdk/resources/machines/machines.py b/src/dedalus_sdk/resources/machines/machines.py index 3971492..396bb1d 100644 --- a/src/dedalus_sdk/resources/machines/machines.py +++ b/src/dedalus_sdk/resources/machines/machines.py @@ -1,9 +1,46 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.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, strip_not_given +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...pagination import SyncCursorPage, AsyncCursorPage +from ..._base_client import AsyncPaginator, make_request_options +from ..._streaming import Stream, AsyncStream +from .network import ( + NetworkResource, + AsyncNetworkResource, + NetworkResourceWithRawResponse, + AsyncNetworkResourceWithRawResponse, + NetworkResourceWithStreamingResponse, + AsyncNetworkResourceWithStreamingResponse, +) +from .artifacts import ( + ArtifactsResource, + AsyncArtifactsResource, + ArtifactsResourceWithRawResponse, + AsyncArtifactsResourceWithRawResponse, + ArtifactsResourceWithStreamingResponse, + AsyncArtifactsResourceWithStreamingResponse, +) +from .ports import ( + PortsResource, + AsyncPortsResource, + PortsResourceWithRawResponse, + AsyncPortsResourceWithRawResponse, + PortsResourceWithStreamingResponse, + AsyncPortsResourceWithStreamingResponse, +) from .ssh import ( SSHResource, AsyncSSHResource, @@ -12,10 +49,6 @@ SSHResourceWithStreamingResponse, AsyncSSHResourceWithStreamingResponse, ) -from ...types import machine_list_params, machine_create_params, machine_update_params -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 .executions import ( ExecutionsResource, AsyncExecutionsResource, @@ -24,23 +57,35 @@ ExecutionsResourceWithStreamingResponse, AsyncExecutionsResourceWithStreamingResponse, ) -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 .terminals import ( + TerminalsResource, + AsyncTerminalsResource, + TerminalsResourceWithRawResponse, + AsyncTerminalsResourceWithRawResponse, + TerminalsResourceWithStreamingResponse, + AsyncTerminalsResourceWithStreamingResponse, ) -from ...pagination import SyncCursorPage, AsyncCursorPage -from ..._base_client import AsyncPaginator, make_request_options -from ...types.machine import Machine +from ...types import machine_list_params, machine_create_params, machine_update_params from ...types.machine_list_item import MachineListItem +from ...types.machine import Machine from ...types.machine_retrieve_response import MachineRetrieveResponse __all__ = ["MachinesResource", "AsyncMachinesResource"] class MachinesResource(SyncAPIResource): + @cached_property + def network(self) -> NetworkResource: + return NetworkResource(self._client) + + @cached_property + def artifacts(self) -> ArtifactsResource: + return ArtifactsResource(self._client) + + @cached_property + def ports(self) -> PortsResource: + return PortsResource(self._client) + @cached_property def ssh(self) -> SSHResource: return SSHResource(self._client) @@ -50,23 +95,64 @@ def executions(self) -> ExecutionsResource: return ExecutionsResource(self._client) @cached_property - def with_raw_response(self) -> MachinesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. + def terminals(self) -> TerminalsResource: + return TerminalsResource(self._client) - For more information, see https://www.github.com/dedalus-labs/dedalus-python#accessing-raw-response-data-eg-headers - """ + @cached_property + def with_raw_response(self) -> MachinesResourceWithRawResponse: return MachinesResourceWithRawResponse(self) @cached_property def with_streaming_response(self) -> MachinesResourceWithStreamingResponse: + return MachinesResourceWithStreamingResponse(self) + + def list( + self, + *, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> SyncCursorPage[MachineListItem]: """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. + List machines - For more information, see https://www.github.com/dedalus-labs/dedalus-python#with_streaming_response + Args: + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SyncCursorPage[MachineListItem]: OK + + Example: + ```python + page = client.machines.list() + ``` """ - return MachinesResourceWithStreamingResponse(self) + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + "/v1/machines", + page=SyncCursorPage[MachineListItem], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, machine_list_params.MachineListParams), + ), + model=MachineListItem, + method="get", + ) def create( self, @@ -75,6 +161,7 @@ def create( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, + x_dedalus_org_id: 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, @@ -83,30 +170,36 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, idempotency_key: str | None = None, ) -> Machine: - """Create machine + """ + Create 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. - - vcpu: CPU in vCPUs. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + 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. + vcpu: CPU in vCPUs. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: Create converged inline + + Example: + ```python + machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", + ) + ``` """ + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( "/v1/machines", body=maybe_transform( @@ -132,6 +225,7 @@ def retrieve( self, *, machine_id: str, + x_dedalus_org_id: 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, @@ -143,18 +237,28 @@ def retrieve( Get machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineRetrieveResponse: OK + + Example: + ```python + machine = client.machines.retrieve( + machine_id="machineID", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get( - path_template("/v1/machines/{machine_id}", machine_id=machine_id), + path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -169,6 +273,7 @@ def update( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, + x_dedalus_org_id: 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, @@ -177,34 +282,38 @@ 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. - - vcpu: CPU in vCPUs. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + 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. + vcpu: CPU in vCPUs. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = client.machines.update( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._patch( - path_template("/v1/machines/{machine_id}", machine_id=machine_id), + path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), body=maybe_transform( { "autosleep": autosleep, @@ -224,93 +333,117 @@ def update( cast_to=Machine, ) - def list( + def delete( self, *, - cursor: str | Omit = omit, - limit: int | Omit = omit, + machine_id: str, + x_dedalus_org_id: 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, - ) -> SyncCursorPage[MachineListItem]: + idempotency_key: str | None = None, + ) -> Machine: """ - List machines + Destroy machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = client.machines.delete( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - return self._get_api_list( - "/v1/machines", - page=SyncCursorPage[MachineListItem], + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._delete( + path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - machine_list_params.MachineListParams, - ), + idempotency_key=idempotency_key, ), - model=MachineListItem, + cast_to=Machine, ) - def delete( + def watch( self, *, machine_id: str, + x_dedalus_org_id: str | Omit = omit, + last_event_id: 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, - idempotency_key: str | None = None, - ) -> Machine: + ) -> Stream[Machine]: """ - Destroy machine + Streams machine lifecycle updates over Server-Sent Events. Each `status` event contains a full `LifecycleResponse` payload. The stream closes after the machine reaches its current desired state. Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Machine identifier. + x_dedalus_org_id: Organization ID header applied to all DCS requests. + last_event_id: Optional resourceVersion bookmark used to resume a previous stream. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Stream[Machine]: Server-Sent Event stream (`text/event-stream`) of machine lifecycle updates. + + Example: + ```python + stream = client.machines.watch( + machine_id="machineID", + ) + + for machine in stream: + print(machine) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return self._delete( - path_template("/v1/machines/{machine_id}", machine_id=machine_id), + extra_headers = { + **strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id, "Last-Event-ID": last_event_id}), + **(extra_headers or {}), + } + extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} + return self._get( + path_template("/v1/machines/{machine_id}/status/stream", **{"machine_id": machine_id}), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Machine, + stream=True, + stream_cls=Stream[Machine], ) def sleep( self, *, machine_id: str, + x_dedalus_org_id: 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, @@ -323,20 +456,30 @@ def sleep( Sleep a running machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = client.machines.sleep( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( - path_template("/v1/machines/{machine_id}/sleep", machine_id=machine_id), + path_template("/v1/machines/{machine_id}/sleep", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -351,6 +494,7 @@ def wake( self, *, machine_id: str, + x_dedalus_org_id: 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, @@ -363,20 +507,30 @@ def wake( Wake a sleeping machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = client.machines.wake( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( - path_template("/v1/machines/{machine_id}/wake", machine_id=machine_id), + path_template("/v1/machines/{machine_id}/wake", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -389,6 +543,18 @@ def wake( class AsyncMachinesResource(AsyncAPIResource): + @cached_property + def network(self) -> AsyncNetworkResource: + return AsyncNetworkResource(self._client) + + @cached_property + def artifacts(self) -> AsyncArtifactsResource: + return AsyncArtifactsResource(self._client) + + @cached_property + def ports(self) -> AsyncPortsResource: + return AsyncPortsResource(self._client) + @cached_property def ssh(self) -> AsyncSSHResource: return AsyncSSHResource(self._client) @@ -398,23 +564,64 @@ def executions(self) -> AsyncExecutionsResource: return AsyncExecutionsResource(self._client) @cached_property - def with_raw_response(self) -> AsyncMachinesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. + def terminals(self) -> AsyncTerminalsResource: + return AsyncTerminalsResource(self._client) - For more information, see https://www.github.com/dedalus-labs/dedalus-python#accessing-raw-response-data-eg-headers - """ + @cached_property + def with_raw_response(self) -> AsyncMachinesResourceWithRawResponse: return AsyncMachinesResourceWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncMachinesResourceWithStreamingResponse: + return AsyncMachinesResourceWithStreamingResponse(self) + + def list( + self, + *, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> AsyncPaginator[MachineListItem, AsyncCursorPage[MachineListItem]]: """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. + List machines - For more information, see https://www.github.com/dedalus-labs/dedalus-python#with_streaming_response + Args: + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncPaginator[MachineListItem, AsyncCursorPage[MachineListItem]]: OK + + Example: + ```python + page = client.machines.list() + ``` """ - return AsyncMachinesResourceWithStreamingResponse(self) + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + "/v1/machines", + page=AsyncCursorPage[MachineListItem], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, machine_list_params.MachineListParams), + ), + model=MachineListItem, + method="get", + ) async def create( self, @@ -423,6 +630,7 @@ async def create( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, + x_dedalus_org_id: 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, @@ -431,30 +639,36 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, idempotency_key: str | None = None, ) -> Machine: - """Create machine + """ + Create 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. - - vcpu: CPU in vCPUs. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + 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. + vcpu: CPU in vCPUs. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: Create converged inline + + Example: + ```python + machine = await client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", + ) + ``` """ + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( "/v1/machines", body=await async_maybe_transform( @@ -480,6 +694,7 @@ async def retrieve( self, *, machine_id: str, + x_dedalus_org_id: 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, @@ -491,18 +706,28 @@ async def retrieve( Get machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineRetrieveResponse: OK + + Example: + ```python + machine = await client.machines.retrieve( + machine_id="machineID", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._get( - path_template("/v1/machines/{machine_id}", machine_id=machine_id), + path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -517,6 +742,7 @@ async def update( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, + x_dedalus_org_id: 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,34 +751,38 @@ 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. - - vcpu: CPU in vCPUs. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + 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. + vcpu: CPU in vCPUs. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = await client.machines.update( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._patch( - path_template("/v1/machines/{machine_id}", machine_id=machine_id), + path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), body=await async_maybe_transform( { "autosleep": autosleep, @@ -572,93 +802,117 @@ async def update( cast_to=Machine, ) - def list( + async def delete( self, *, - cursor: str | Omit = omit, - limit: int | Omit = omit, + machine_id: str, + x_dedalus_org_id: 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, - ) -> AsyncPaginator[MachineListItem, AsyncCursorPage[MachineListItem]]: + idempotency_key: str | None = None, + ) -> Machine: """ - List machines + Destroy machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = await client.machines.delete( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - return self._get_api_list( - "/v1/machines", - page=AsyncCursorPage[MachineListItem], + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._delete( + path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - machine_list_params.MachineListParams, - ), + idempotency_key=idempotency_key, ), - model=MachineListItem, + cast_to=Machine, ) - async def delete( + async def watch( self, *, machine_id: str, + x_dedalus_org_id: str | Omit = omit, + last_event_id: 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, - idempotency_key: str | None = None, - ) -> Machine: + ) -> AsyncStream[Machine]: """ - Destroy machine + Streams machine lifecycle updates over Server-Sent Events. Each `status` event contains a full `LifecycleResponse` payload. The stream closes after the machine reaches its current desired state. Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Machine identifier. + x_dedalus_org_id: Organization ID header applied to all DCS requests. + last_event_id: Optional resourceVersion bookmark used to resume a previous stream. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncStream[Machine]: Server-Sent Event stream (`text/event-stream`) of machine lifecycle updates. + + Example: + ```python + stream = await client.machines.watch( + machine_id="machineID", + ) + + async for machine in stream: + print(machine) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return await self._delete( - path_template("/v1/machines/{machine_id}", machine_id=machine_id), + extra_headers = { + **strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id, "Last-Event-ID": last_event_id}), + **(extra_headers or {}), + } + extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} + return await self._get( + path_template("/v1/machines/{machine_id}/status/stream", **{"machine_id": machine_id}), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=Machine, + stream=True, + stream_cls=AsyncStream[Machine], ) async def sleep( self, *, machine_id: str, + x_dedalus_org_id: 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, @@ -671,20 +925,30 @@ async def sleep( Sleep a running machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = await client.machines.sleep( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( - path_template("/v1/machines/{machine_id}/sleep", machine_id=machine_id), + path_template("/v1/machines/{machine_id}/sleep", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -699,6 +963,7 @@ async def wake( self, *, machine_id: str, + x_dedalus_org_id: 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, @@ -711,20 +976,30 @@ async def wake( Wake a sleeping machine Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = await client.machines.wake( + machine_id="machineID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( - path_template("/v1/machines/{machine_id}/wake", machine_id=machine_id), + path_template("/v1/machines/{machine_id}/wake", **{"machine_id": machine_id}), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -740,6 +1015,9 @@ class MachinesResourceWithRawResponse: def __init__(self, machines: MachinesResource) -> None: self._machines = machines + self.list = to_raw_response_wrapper( + machines.list, + ) self.create = to_raw_response_wrapper( machines.create, ) @@ -749,12 +1027,12 @@ def __init__(self, machines: MachinesResource) -> None: self.update = to_raw_response_wrapper( machines.update, ) - self.list = to_raw_response_wrapper( - machines.list, - ) self.delete = to_raw_response_wrapper( machines.delete, ) + self.watch = to_raw_response_wrapper( + machines.watch, + ) self.sleep = to_raw_response_wrapper( machines.sleep, ) @@ -762,6 +1040,18 @@ def __init__(self, machines: MachinesResource) -> None: machines.wake, ) + @cached_property + def network(self) -> NetworkResourceWithRawResponse: + return NetworkResourceWithRawResponse(self._machines.network) + + @cached_property + def artifacts(self) -> ArtifactsResourceWithRawResponse: + return ArtifactsResourceWithRawResponse(self._machines.artifacts) + + @cached_property + def ports(self) -> PortsResourceWithRawResponse: + return PortsResourceWithRawResponse(self._machines.ports) + @cached_property def ssh(self) -> SSHResourceWithRawResponse: return SSHResourceWithRawResponse(self._machines.ssh) @@ -770,11 +1060,18 @@ def ssh(self) -> SSHResourceWithRawResponse: def executions(self) -> ExecutionsResourceWithRawResponse: return ExecutionsResourceWithRawResponse(self._machines.executions) + @cached_property + def terminals(self) -> TerminalsResourceWithRawResponse: + return TerminalsResourceWithRawResponse(self._machines.terminals) + class AsyncMachinesResourceWithRawResponse: def __init__(self, machines: AsyncMachinesResource) -> None: self._machines = machines + self.list = async_to_raw_response_wrapper( + machines.list, + ) self.create = async_to_raw_response_wrapper( machines.create, ) @@ -784,12 +1081,12 @@ def __init__(self, machines: AsyncMachinesResource) -> None: self.update = async_to_raw_response_wrapper( machines.update, ) - self.list = async_to_raw_response_wrapper( - machines.list, - ) self.delete = async_to_raw_response_wrapper( machines.delete, ) + self.watch = async_to_raw_response_wrapper( + machines.watch, + ) self.sleep = async_to_raw_response_wrapper( machines.sleep, ) @@ -797,6 +1094,18 @@ def __init__(self, machines: AsyncMachinesResource) -> None: machines.wake, ) + @cached_property + def network(self) -> AsyncNetworkResourceWithRawResponse: + return AsyncNetworkResourceWithRawResponse(self._machines.network) + + @cached_property + def artifacts(self) -> AsyncArtifactsResourceWithRawResponse: + return AsyncArtifactsResourceWithRawResponse(self._machines.artifacts) + + @cached_property + def ports(self) -> AsyncPortsResourceWithRawResponse: + return AsyncPortsResourceWithRawResponse(self._machines.ports) + @cached_property def ssh(self) -> AsyncSSHResourceWithRawResponse: return AsyncSSHResourceWithRawResponse(self._machines.ssh) @@ -805,11 +1114,18 @@ def ssh(self) -> AsyncSSHResourceWithRawResponse: def executions(self) -> AsyncExecutionsResourceWithRawResponse: return AsyncExecutionsResourceWithRawResponse(self._machines.executions) + @cached_property + def terminals(self) -> AsyncTerminalsResourceWithRawResponse: + return AsyncTerminalsResourceWithRawResponse(self._machines.terminals) + class MachinesResourceWithStreamingResponse: def __init__(self, machines: MachinesResource) -> None: self._machines = machines + self.list = to_streamed_response_wrapper( + machines.list, + ) self.create = to_streamed_response_wrapper( machines.create, ) @@ -819,12 +1135,12 @@ def __init__(self, machines: MachinesResource) -> None: self.update = to_streamed_response_wrapper( machines.update, ) - self.list = to_streamed_response_wrapper( - machines.list, - ) self.delete = to_streamed_response_wrapper( machines.delete, ) + self.watch = to_streamed_response_wrapper( + machines.watch, + ) self.sleep = to_streamed_response_wrapper( machines.sleep, ) @@ -832,6 +1148,18 @@ def __init__(self, machines: MachinesResource) -> None: machines.wake, ) + @cached_property + def network(self) -> NetworkResourceWithStreamingResponse: + return NetworkResourceWithStreamingResponse(self._machines.network) + + @cached_property + def artifacts(self) -> ArtifactsResourceWithStreamingResponse: + return ArtifactsResourceWithStreamingResponse(self._machines.artifacts) + + @cached_property + def ports(self) -> PortsResourceWithStreamingResponse: + return PortsResourceWithStreamingResponse(self._machines.ports) + @cached_property def ssh(self) -> SSHResourceWithStreamingResponse: return SSHResourceWithStreamingResponse(self._machines.ssh) @@ -840,11 +1168,18 @@ def ssh(self) -> SSHResourceWithStreamingResponse: def executions(self) -> ExecutionsResourceWithStreamingResponse: return ExecutionsResourceWithStreamingResponse(self._machines.executions) + @cached_property + def terminals(self) -> TerminalsResourceWithStreamingResponse: + return TerminalsResourceWithStreamingResponse(self._machines.terminals) + class AsyncMachinesResourceWithStreamingResponse: def __init__(self, machines: AsyncMachinesResource) -> None: self._machines = machines + self.list = async_to_streamed_response_wrapper( + machines.list, + ) self.create = async_to_streamed_response_wrapper( machines.create, ) @@ -854,12 +1189,12 @@ def __init__(self, machines: AsyncMachinesResource) -> None: self.update = async_to_streamed_response_wrapper( machines.update, ) - self.list = async_to_streamed_response_wrapper( - machines.list, - ) self.delete = async_to_streamed_response_wrapper( machines.delete, ) + self.watch = async_to_streamed_response_wrapper( + machines.watch, + ) self.sleep = async_to_streamed_response_wrapper( machines.sleep, ) @@ -867,6 +1202,18 @@ def __init__(self, machines: AsyncMachinesResource) -> None: machines.wake, ) + @cached_property + def network(self) -> AsyncNetworkResourceWithStreamingResponse: + return AsyncNetworkResourceWithStreamingResponse(self._machines.network) + + @cached_property + def artifacts(self) -> AsyncArtifactsResourceWithStreamingResponse: + return AsyncArtifactsResourceWithStreamingResponse(self._machines.artifacts) + + @cached_property + def ports(self) -> AsyncPortsResourceWithStreamingResponse: + return AsyncPortsResourceWithStreamingResponse(self._machines.ports) + @cached_property def ssh(self) -> AsyncSSHResourceWithStreamingResponse: return AsyncSSHResourceWithStreamingResponse(self._machines.ssh) @@ -874,3 +1221,7 @@ def ssh(self) -> AsyncSSHResourceWithStreamingResponse: @cached_property def executions(self) -> AsyncExecutionsResourceWithStreamingResponse: return AsyncExecutionsResourceWithStreamingResponse(self._machines.executions) + + @cached_property + def terminals(self) -> AsyncTerminalsResourceWithStreamingResponse: + return AsyncTerminalsResourceWithStreamingResponse(self._machines.terminals) diff --git a/src/dedalus_sdk/resources/machines/network.py b/src/dedalus_sdk/resources/machines/network.py new file mode 100644 index 0000000..de66baf --- /dev/null +++ b/src/dedalus_sdk/resources/machines/network.py @@ -0,0 +1,164 @@ +# File generated from our OpenAPI spec by Scalar. See README.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, strip_not_given +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.machines.machine_network import MachineNetwork + +__all__ = ["NetworkResource", "AsyncNetworkResource"] + + +class NetworkResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> NetworkResourceWithRawResponse: + return NetworkResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> NetworkResourceWithStreamingResponse: + return NetworkResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + machine_id: str, + x_dedalus_org_id: 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, + ) -> MachineNetwork: + """ + Get machine network identity + + Args: + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineNetwork: OK + + Example: + ```python + network = client.machines.network.retrieve( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get( + path_template("/v1/machines/{machine_id}/network", **{"machine_id": machine_id}), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MachineNetwork, + ) + + +class AsyncNetworkResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncNetworkResourceWithRawResponse: + return AsyncNetworkResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncNetworkResourceWithStreamingResponse: + return AsyncNetworkResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + machine_id: str, + x_dedalus_org_id: 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, + ) -> MachineNetwork: + """ + Get machine network identity + + Args: + machine_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineNetwork: OK + + Example: + ```python + network = await client.machines.network.retrieve( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._get( + path_template("/v1/machines/{machine_id}/network", **{"machine_id": machine_id}), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MachineNetwork, + ) + + +class NetworkResourceWithRawResponse: + def __init__(self, network: NetworkResource) -> None: + self._network = network + + self.retrieve = to_raw_response_wrapper( + network.retrieve, + ) + + +class AsyncNetworkResourceWithRawResponse: + def __init__(self, network: AsyncNetworkResource) -> None: + self._network = network + + self.retrieve = async_to_raw_response_wrapper( + network.retrieve, + ) + + +class NetworkResourceWithStreamingResponse: + def __init__(self, network: NetworkResource) -> None: + self._network = network + + self.retrieve = to_streamed_response_wrapper( + network.retrieve, + ) + + +class AsyncNetworkResourceWithStreamingResponse: + def __init__(self, network: AsyncNetworkResource) -> None: + self._network = network + + self.retrieve = async_to_streamed_response_wrapper( + network.retrieve, + ) diff --git a/src/dedalus_sdk/resources/machines/ports.py b/src/dedalus_sdk/resources/machines/ports.py new file mode 100644 index 0000000..40c87e8 --- /dev/null +++ b/src/dedalus_sdk/resources/machines/ports.py @@ -0,0 +1,568 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import httpx + +from typing_extensions import Literal + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform, strip_not_given +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...pagination import SyncCursorPage, AsyncCursorPage +from ..._base_client import AsyncPaginator, make_request_options +from ...types.machines import port_list_params, port_create_params +from ...types.machines.port import Port + +__all__ = ["PortsResource", "AsyncPortsResource"] + + +class PortsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> PortsResourceWithRawResponse: + return PortsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PortsResourceWithStreamingResponse: + return PortsResourceWithStreamingResponse(self) + + def list( + self, + *, + machine_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> SyncCursorPage[Port]: + """ + List ports + + Args: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SyncCursorPage[Port]: OK + + Example: + ```python + page = client.machines.ports.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), + page=SyncCursorPage[Port], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, port_list_params.PortListParams), + ), + model=Port, + method="get", + ) + + def create( + self, + *, + machine_id: str, + port: int, + protocol: Literal["http", "https"] | Omit = omit, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Port: + """ + Create port + + Args: + machine_id: Path parameter. + port: Body parameter. + protocol: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Port: OK + + Example: + ```python + port = client.machines.ports.create( + machine_id="machineID", + port=0, + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._post( + path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), + body=maybe_transform( + { + "port": port, + "protocol": protocol, + }, + port_create_params.PortCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Port, + ) + + def retrieve( + self, + *, + machine_id: str, + port_id: str, + x_dedalus_org_id: 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, + ) -> Port: + """ + Get port + + Args: + machine_id: Path parameter. + port_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Port: OK + + Example: + ```python + port = client.machines.ports.retrieve( + machine_id="machineID", + port_id="portID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if port_id is None or (isinstance(port_id, str) and not port_id): + raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get( + path_template( + "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Port, + ) + + def delete( + self, + *, + machine_id: str, + port_id: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Port: + """ + Delete port + + Args: + machine_id: Path parameter. + port_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Port: OK + + Example: + ```python + port = client.machines.ports.delete( + machine_id="machineID", + port_id="portID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if port_id is None or (isinstance(port_id, str) and not port_id): + raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._delete( + path_template( + "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Port, + ) + + +class AsyncPortsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncPortsResourceWithRawResponse: + return AsyncPortsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPortsResourceWithStreamingResponse: + return AsyncPortsResourceWithStreamingResponse(self) + + def list( + self, + *, + machine_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> AsyncPaginator[Port, AsyncCursorPage[Port]]: + """ + List ports + + Args: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncPaginator[Port, AsyncCursorPage[Port]]: OK + + Example: + ```python + page = client.machines.ports.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), + page=AsyncCursorPage[Port], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, port_list_params.PortListParams), + ), + model=Port, + method="get", + ) + + async def create( + self, + *, + machine_id: str, + port: int, + protocol: Literal["http", "https"] | Omit = omit, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Port: + """ + Create port + + Args: + machine_id: Path parameter. + port: Body parameter. + protocol: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Port: OK + + Example: + ```python + port = await client.machines.ports.create( + machine_id="machineID", + port=0, + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._post( + path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), + body=await async_maybe_transform( + { + "port": port, + "protocol": protocol, + }, + port_create_params.PortCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Port, + ) + + async def retrieve( + self, + *, + machine_id: str, + port_id: str, + x_dedalus_org_id: 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, + ) -> Port: + """ + Get port + + Args: + machine_id: Path parameter. + port_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Port: OK + + Example: + ```python + port = await client.machines.ports.retrieve( + machine_id="machineID", + port_id="portID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if port_id is None or (isinstance(port_id, str) and not port_id): + raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._get( + path_template( + "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Port, + ) + + async def delete( + self, + *, + machine_id: str, + port_id: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Port: + """ + Delete port + + Args: + machine_id: Path parameter. + port_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Port: OK + + Example: + ```python + port = await client.machines.ports.delete( + machine_id="machineID", + port_id="portID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if port_id is None or (isinstance(port_id, str) and not port_id): + raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._delete( + path_template( + "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Port, + ) + + +class PortsResourceWithRawResponse: + def __init__(self, ports: PortsResource) -> None: + self._ports = ports + + self.list = to_raw_response_wrapper( + ports.list, + ) + self.create = to_raw_response_wrapper( + ports.create, + ) + self.retrieve = to_raw_response_wrapper( + ports.retrieve, + ) + self.delete = to_raw_response_wrapper( + ports.delete, + ) + + +class AsyncPortsResourceWithRawResponse: + def __init__(self, ports: AsyncPortsResource) -> None: + self._ports = ports + + self.list = async_to_raw_response_wrapper( + ports.list, + ) + self.create = async_to_raw_response_wrapper( + ports.create, + ) + self.retrieve = async_to_raw_response_wrapper( + ports.retrieve, + ) + self.delete = async_to_raw_response_wrapper( + ports.delete, + ) + + +class PortsResourceWithStreamingResponse: + def __init__(self, ports: PortsResource) -> None: + self._ports = ports + + self.list = to_streamed_response_wrapper( + ports.list, + ) + self.create = to_streamed_response_wrapper( + ports.create, + ) + self.retrieve = to_streamed_response_wrapper( + ports.retrieve, + ) + self.delete = to_streamed_response_wrapper( + ports.delete, + ) + + +class AsyncPortsResourceWithStreamingResponse: + def __init__(self, ports: AsyncPortsResource) -> None: + self._ports = ports + + self.list = async_to_streamed_response_wrapper( + ports.list, + ) + self.create = async_to_streamed_response_wrapper( + ports.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + ports.retrieve, + ) + self.delete = async_to_streamed_response_wrapper( + ports.delete, + ) diff --git a/src/dedalus_sdk/resources/machines/ssh.py b/src/dedalus_sdk/resources/machines/ssh.py index 041e445..64bc0ff 100644 --- a/src/dedalus_sdk/resources/machines/ssh.py +++ b/src/dedalus_sdk/resources/machines/ssh.py @@ -1,11 +1,11 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.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 ..._utils import path_template, maybe_transform, async_maybe_transform, strip_not_given from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -25,145 +25,173 @@ class SSHResource(SyncAPIResource): @cached_property def with_raw_response(self) -> SSHResourceWithRawResponse: - """ - 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 SSHResourceWithRawResponse(self) @cached_property def with_streaming_response(self) -> SSHResourceWithStreamingResponse: - """ - 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 SSHResourceWithStreamingResponse(self) - def create( + def list( self, *, machine_id: str, - public_key: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> SSHSession: + ) -> SyncCursorPage[SSHSession]: """ - Create SSH session + List SSH sessions Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SyncCursorPage[SSHSession]: OK + + Example: + ```python + page = client.machines.ssh.list( + machine_id="machineID", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return self._post( - path_template("/v1/machines/{machine_id}/ssh", machine_id=machine_id), - body=maybe_transform({"public_key": public_key}, ssh_create_params.SSHCreateParams), + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), + page=SyncCursorPage[SSHSession], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - idempotency_key=idempotency_key, + query=maybe_transform({"limit": limit, "cursor": cursor}, ssh_list_params.SSHListParams), ), - cast_to=SSHSession, + model=SSHSession, + method="get", ) - def retrieve( + def create( self, *, machine_id: str, - session_id: str, + public_key: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, ) -> SSHSession: """ - Get SSH session + Create SSH session Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + public_key: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + SSHSession: OK + + Example: + ```python + ssh = client.machines.ssh.create( + machine_id="machineID", + public_key="", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not session_id: - raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") - return self._get( - path_template("/v1/machines/{machine_id}/ssh/{session_id}", machine_id=machine_id, session_id=session_id), + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._post( + path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), + body=maybe_transform( + {"public_key": public_key}, + ssh_create_params.SSHCreateParams, + ), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, ), cast_to=SSHSession, ) - def list( + def retrieve( self, *, machine_id: str, - cursor: str | Omit = omit, - limit: int | Omit = omit, + session_id: str, + x_dedalus_org_id: 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, - ) -> SyncCursorPage[SSHSession]: + ) -> SSHSession: """ - List SSH sessions + Get SSH session Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + session_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SSHSession: OK + + Example: + ```python + ssh = client.machines.ssh.retrieve( + machine_id="machineID", + session_id="sessionID", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return self._get_api_list( - path_template("/v1/machines/{machine_id}/ssh", machine_id=machine_id), - page=SyncCursorPage[SSHSession], + if session_id is None or (isinstance(session_id, str) and not session_id): + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get( + path_template( + "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - ssh_list_params.SSHListParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - model=SSHSession, + cast_to=SSHSession, ) def delete( @@ -171,6 +199,7 @@ def delete( *, machine_id: str, session_id: str, + x_dedalus_org_id: 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, @@ -183,22 +212,36 @@ def delete( Delete SSH session Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + session_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + SSHSession: OK + + Example: + ```python + ssh = client.machines.ssh.delete( + machine_id="machineID", + session_id="sessionID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not session_id: + if session_id is None or (isinstance(session_id, str) and not session_id): raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._delete( - path_template("/v1/machines/{machine_id}/ssh/{session_id}", machine_id=machine_id, session_id=session_id), + path_template( + "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -213,145 +256,173 @@ def delete( class AsyncSSHResource(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncSSHResourceWithRawResponse: - """ - 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 AsyncSSHResourceWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncSSHResourceWithStreamingResponse: - """ - 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 AsyncSSHResourceWithStreamingResponse(self) - async def create( + def list( self, *, machine_id: str, - public_key: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> SSHSession: + ) -> AsyncPaginator[SSHSession, AsyncCursorPage[SSHSession]]: """ - Create SSH session + List SSH sessions Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncPaginator[SSHSession, AsyncCursorPage[SSHSession]]: OK + + Example: + ```python + page = client.machines.ssh.list( + machine_id="machineID", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return await self._post( - path_template("/v1/machines/{machine_id}/ssh", machine_id=machine_id), - body=await async_maybe_transform({"public_key": public_key}, ssh_create_params.SSHCreateParams), + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), + page=AsyncCursorPage[SSHSession], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - idempotency_key=idempotency_key, + query=maybe_transform({"limit": limit, "cursor": cursor}, ssh_list_params.SSHListParams), ), - cast_to=SSHSession, + model=SSHSession, + method="get", ) - async def retrieve( + async def create( self, *, machine_id: str, - session_id: str, + public_key: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, ) -> SSHSession: """ - Get SSH session + Create SSH session Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + public_key: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + SSHSession: OK + + Example: + ```python + ssh = await client.machines.ssh.create( + machine_id="machineID", + public_key="", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not session_id: - raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") - return await self._get( - path_template("/v1/machines/{machine_id}/ssh/{session_id}", machine_id=machine_id, session_id=session_id), + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._post( + path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), + body=await async_maybe_transform( + {"public_key": public_key}, + ssh_create_params.SSHCreateParams, + ), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, ), cast_to=SSHSession, ) - def list( + async def retrieve( self, *, machine_id: str, - cursor: str | Omit = omit, - limit: int | Omit = omit, + session_id: str, + x_dedalus_org_id: 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, - ) -> AsyncPaginator[SSHSession, AsyncCursorPage[SSHSession]]: + ) -> SSHSession: """ - List SSH sessions + Get SSH session Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds + machine_id: Path parameter. + session_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SSHSession: OK + + Example: + ```python + ssh = await client.machines.ssh.retrieve( + machine_id="machineID", + session_id="sessionID", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - return self._get_api_list( - path_template("/v1/machines/{machine_id}/ssh", machine_id=machine_id), - page=AsyncCursorPage[SSHSession], + if session_id is None or (isinstance(session_id, str) and not session_id): + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._get( + path_template( + "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "cursor": cursor, - "limit": limit, - }, - ssh_list_params.SSHListParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - model=SSHSession, + cast_to=SSHSession, ) async def delete( @@ -359,6 +430,7 @@ async def delete( *, machine_id: str, session_id: str, + x_dedalus_org_id: 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, @@ -371,22 +443,36 @@ async def delete( Delete SSH session Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - - idempotency_key: Specify a custom idempotency key for this request + machine_id: Path parameter. + session_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + SSHSession: OK + + Example: + ```python + ssh = await client.machines.ssh.delete( + machine_id="machineID", + session_id="sessionID", + idempotency_key="", + ) + ``` """ - if not machine_id: + if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if not session_id: + if session_id is None or (isinstance(session_id, str) and not session_id): raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._delete( - path_template("/v1/machines/{machine_id}/ssh/{session_id}", machine_id=machine_id, session_id=session_id), + path_template( + "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} + ), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -402,15 +488,15 @@ class SSHResourceWithRawResponse: def __init__(self, ssh: SSHResource) -> None: self._ssh = ssh + self.list = to_raw_response_wrapper( + ssh.list, + ) self.create = to_raw_response_wrapper( ssh.create, ) self.retrieve = to_raw_response_wrapper( ssh.retrieve, ) - self.list = to_raw_response_wrapper( - ssh.list, - ) self.delete = to_raw_response_wrapper( ssh.delete, ) @@ -420,15 +506,15 @@ class AsyncSSHResourceWithRawResponse: def __init__(self, ssh: AsyncSSHResource) -> None: self._ssh = ssh + self.list = async_to_raw_response_wrapper( + ssh.list, + ) self.create = async_to_raw_response_wrapper( ssh.create, ) self.retrieve = async_to_raw_response_wrapper( ssh.retrieve, ) - self.list = async_to_raw_response_wrapper( - ssh.list, - ) self.delete = async_to_raw_response_wrapper( ssh.delete, ) @@ -438,15 +524,15 @@ class SSHResourceWithStreamingResponse: def __init__(self, ssh: SSHResource) -> None: self._ssh = ssh + self.list = to_streamed_response_wrapper( + ssh.list, + ) self.create = to_streamed_response_wrapper( ssh.create, ) self.retrieve = to_streamed_response_wrapper( ssh.retrieve, ) - self.list = to_streamed_response_wrapper( - ssh.list, - ) self.delete = to_streamed_response_wrapper( ssh.delete, ) @@ -456,15 +542,15 @@ class AsyncSSHResourceWithStreamingResponse: def __init__(self, ssh: AsyncSSHResource) -> None: self._ssh = ssh + self.list = async_to_streamed_response_wrapper( + ssh.list, + ) self.create = async_to_streamed_response_wrapper( ssh.create, ) self.retrieve = async_to_streamed_response_wrapper( ssh.retrieve, ) - self.list = async_to_streamed_response_wrapper( - ssh.list, - ) self.delete = async_to_streamed_response_wrapper( ssh.delete, ) diff --git a/src/dedalus_sdk/resources/machines/terminals/__init__.py b/src/dedalus_sdk/resources/machines/terminals/__init__.py new file mode 100644 index 0000000..94e2e99 --- /dev/null +++ b/src/dedalus_sdk/resources/machines/terminals/__init__.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from .terminals import ( + TerminalsResource, + AsyncTerminalsResource, + TerminalsResourceWithRawResponse, + AsyncTerminalsResourceWithRawResponse, + TerminalsResourceWithStreamingResponse, + AsyncTerminalsResourceWithStreamingResponse, + TerminalsResourceConnectionManager, + AsyncTerminalsResourceConnectionManager, + TerminalsResourceConnection, + AsyncTerminalsResourceConnection, +) + +__all__ = [ + "TerminalsResource", + "AsyncTerminalsResource", + "TerminalsResourceWithRawResponse", + "AsyncTerminalsResourceWithRawResponse", + "TerminalsResourceWithStreamingResponse", + "AsyncTerminalsResourceWithStreamingResponse", + "TerminalsResourceConnectionManager", + "AsyncTerminalsResourceConnectionManager", + "TerminalsResourceConnection", + "AsyncTerminalsResourceConnection", +] diff --git a/src/dedalus_sdk/resources/machines/terminals/terminals.py b/src/dedalus_sdk/resources/machines/terminals/terminals.py new file mode 100644 index 0000000..f2a95a9 --- /dev/null +++ b/src/dedalus_sdk/resources/machines/terminals/terminals.py @@ -0,0 +1,657 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import httpx + +from typing import Dict +from typing import Callable + +from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ...._utils import path_template, maybe_transform, async_maybe_transform, strip_not_given +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ....pagination import SyncCursorPage, AsyncCursorPage +from ...._base_client import AsyncPaginator, make_request_options +from ....types.machines import terminal_list_params, terminal_create_params +from ....types.machines.terminal import Terminal +from ....types.websocket_connection_options import WebSocketConnectionOptions +from ....types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides +from .ws import ( + TerminalsResourceConnectionManager as TerminalsResourceConnectionManager, + AsyncTerminalsResourceConnectionManager as AsyncTerminalsResourceConnectionManager, + TerminalsResourceConnection as TerminalsResourceConnection, + AsyncTerminalsResourceConnection as AsyncTerminalsResourceConnection, +) + +__all__ = ["TerminalsResource", "AsyncTerminalsResource"] + + +class TerminalsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> TerminalsResourceWithRawResponse: + return TerminalsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> TerminalsResourceWithStreamingResponse: + return TerminalsResourceWithStreamingResponse(self) + + def list( + self, + *, + machine_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> SyncCursorPage[Terminal]: + """ + List terminals + + Args: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + SyncCursorPage[Terminal]: OK + + Example: + ```python + page = client.machines.terminals.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), + page=SyncCursorPage[Terminal], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, terminal_list_params.TerminalListParams), + ), + model=Terminal, + method="get", + ) + + def create( + self, + *, + machine_id: str, + cwd: str | Omit = omit, + env: Dict[str, str] | Omit = omit, + height: int, + shell: str | Omit = omit, + width: int, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Terminal: + """ + Create terminal + + Args: + machine_id: Path parameter. + cwd: Body parameter. + env: Body parameter. + height: Body parameter. + shell: Body parameter. + width: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Terminal: OK + + Example: + ```python + terminal = client.machines.terminals.create( + machine_id="machineID", + height=0, + width=0, + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._post( + path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), + body=maybe_transform( + { + "cwd": cwd, + "env": env, + "height": height, + "shell": shell, + "width": width, + }, + terminal_create_params.TerminalCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Terminal, + ) + + def retrieve( + self, + *, + machine_id: str, + terminal_id: str, + x_dedalus_org_id: 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, + ) -> Terminal: + """ + Get terminal + + Args: + machine_id: Path parameter. + terminal_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Terminal: OK + + Example: + ```python + terminal = client.machines.terminals.retrieve( + machine_id="machineID", + terminal_id="terminalID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): + raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get( + path_template( + "/v1/machines/{machine_id}/terminals/{terminal_id}", + **{"machine_id": machine_id, "terminal_id": terminal_id}, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Terminal, + ) + + def delete( + self, + *, + machine_id: str, + terminal_id: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Terminal: + """ + Delete terminal + + Args: + machine_id: Path parameter. + terminal_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Terminal: OK + + Example: + ```python + terminal = client.machines.terminals.delete( + machine_id="machineID", + terminal_id="terminalID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): + raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._delete( + path_template( + "/v1/machines/{machine_id}/terminals/{terminal_id}", + **{"machine_id": machine_id, "terminal_id": terminal_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Terminal, + ) + + def connect( + self, + *, + machine_id: str, + terminal_id: str, + extra_query: Query = {}, + extra_headers: Headers = {}, + websocket_connection_options: WebSocketConnectionOptions = {}, + on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, + max_retries: int = 5, + initial_delay: float = 0.5, + max_delay: float = 8.0, + max_queue_size: int = 1_048_576, + ) -> TerminalsResourceConnectionManager: + return TerminalsResourceConnectionManager( + client=self._client, + machine_id=machine_id, + terminal_id=terminal_id, + extra_query=extra_query, + extra_headers=extra_headers, + websocket_connection_options=websocket_connection_options, + on_reconnecting=on_reconnecting, + max_retries=max_retries, + initial_delay=initial_delay, + max_delay=max_delay, + max_queue_size=max_queue_size, + ) + + +class AsyncTerminalsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncTerminalsResourceWithRawResponse: + return AsyncTerminalsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncTerminalsResourceWithStreamingResponse: + return AsyncTerminalsResourceWithStreamingResponse(self) + + def list( + self, + *, + machine_id: str, + limit: int | Omit = omit, + cursor: str | Omit = omit, + x_dedalus_org_id: 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, + ) -> AsyncPaginator[Terminal, AsyncCursorPage[Terminal]]: + """ + List terminals + + Args: + machine_id: Path parameter. + limit: Query parameter. + cursor: Query parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + AsyncPaginator[Terminal, AsyncCursorPage[Terminal]]: OK + + Example: + ```python + page = client.machines.terminals.list( + machine_id="machineID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get_api_list( + path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), + page=AsyncCursorPage[Terminal], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit, "cursor": cursor}, terminal_list_params.TerminalListParams), + ), + model=Terminal, + method="get", + ) + + async def create( + self, + *, + machine_id: str, + cwd: str | Omit = omit, + env: Dict[str, str] | Omit = omit, + height: int, + shell: str | Omit = omit, + width: int, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Terminal: + """ + Create terminal + + Args: + machine_id: Path parameter. + cwd: Body parameter. + env: Body parameter. + height: Body parameter. + shell: Body parameter. + width: Body parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Terminal: OK + + Example: + ```python + terminal = await client.machines.terminals.create( + machine_id="machineID", + height=0, + width=0, + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._post( + path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), + body=await async_maybe_transform( + { + "cwd": cwd, + "env": env, + "height": height, + "shell": shell, + "width": width, + }, + terminal_create_params.TerminalCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Terminal, + ) + + async def retrieve( + self, + *, + machine_id: str, + terminal_id: str, + x_dedalus_org_id: 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, + ) -> Terminal: + """ + Get terminal + + Args: + machine_id: Path parameter. + terminal_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Terminal: OK + + Example: + ```python + terminal = await client.machines.terminals.retrieve( + machine_id="machineID", + terminal_id="terminalID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): + raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._get( + path_template( + "/v1/machines/{machine_id}/terminals/{terminal_id}", + **{"machine_id": machine_id, "terminal_id": terminal_id}, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Terminal, + ) + + async def delete( + self, + *, + machine_id: str, + terminal_id: str, + x_dedalus_org_id: 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, + idempotency_key: str | None = None, + ) -> Terminal: + """ + Delete terminal + + Args: + machine_id: Path parameter. + terminal_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Terminal: OK + + Example: + ```python + terminal = await client.machines.terminals.delete( + machine_id="machineID", + terminal_id="terminalID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): + raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._delete( + path_template( + "/v1/machines/{machine_id}/terminals/{terminal_id}", + **{"machine_id": machine_id, "terminal_id": terminal_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Terminal, + ) + + def connect( + self, + *, + machine_id: str, + terminal_id: str, + extra_query: Query = {}, + extra_headers: Headers = {}, + websocket_connection_options: WebSocketConnectionOptions = {}, + on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, + max_retries: int = 5, + initial_delay: float = 0.5, + max_delay: float = 8.0, + max_queue_size: int = 1_048_576, + ) -> AsyncTerminalsResourceConnectionManager: + return AsyncTerminalsResourceConnectionManager( + client=self._client, + machine_id=machine_id, + terminal_id=terminal_id, + extra_query=extra_query, + extra_headers=extra_headers, + websocket_connection_options=websocket_connection_options, + on_reconnecting=on_reconnecting, + max_retries=max_retries, + initial_delay=initial_delay, + max_delay=max_delay, + max_queue_size=max_queue_size, + ) + + +class TerminalsResourceWithRawResponse: + def __init__(self, terminals: TerminalsResource) -> None: + self._terminals = terminals + + self.list = to_raw_response_wrapper( + terminals.list, + ) + self.create = to_raw_response_wrapper( + terminals.create, + ) + self.retrieve = to_raw_response_wrapper( + terminals.retrieve, + ) + self.delete = to_raw_response_wrapper( + terminals.delete, + ) + + +class AsyncTerminalsResourceWithRawResponse: + def __init__(self, terminals: AsyncTerminalsResource) -> None: + self._terminals = terminals + + self.list = async_to_raw_response_wrapper( + terminals.list, + ) + self.create = async_to_raw_response_wrapper( + terminals.create, + ) + self.retrieve = async_to_raw_response_wrapper( + terminals.retrieve, + ) + self.delete = async_to_raw_response_wrapper( + terminals.delete, + ) + + +class TerminalsResourceWithStreamingResponse: + def __init__(self, terminals: TerminalsResource) -> None: + self._terminals = terminals + + self.list = to_streamed_response_wrapper( + terminals.list, + ) + self.create = to_streamed_response_wrapper( + terminals.create, + ) + self.retrieve = to_streamed_response_wrapper( + terminals.retrieve, + ) + self.delete = to_streamed_response_wrapper( + terminals.delete, + ) + + +class AsyncTerminalsResourceWithStreamingResponse: + def __init__(self, terminals: AsyncTerminalsResource) -> None: + self._terminals = terminals + + self.list = async_to_streamed_response_wrapper( + terminals.list, + ) + self.create = async_to_streamed_response_wrapper( + terminals.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + terminals.retrieve, + ) + self.delete = async_to_streamed_response_wrapper( + terminals.delete, + ) diff --git a/src/dedalus_sdk/resources/machines/terminals/ws.py b/src/dedalus_sdk/resources/machines/terminals/ws.py new file mode 100644 index 0000000..d168d83 --- /dev/null +++ b/src/dedalus_sdk/resources/machines/terminals/ws.py @@ -0,0 +1,782 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import json +import time +import random +import logging +from types import TracebackType +from typing import TYPE_CHECKING, Any, Union, Callable, Awaitable, Iterator, cast +from typing_extensions import AsyncIterator + +import httpx + +from ...._models import BaseModel, construct_type_unchecked +from ...._types import Headers, Query +from ...._exceptions import DedalusError, WebSocketConnectionClosedError +from ...._send_queue import SendQueue +from ...._base_client import _merge_mappings +from ...._event_handler import EventHandlerRegistry +from ...._utils import path_template, maybe_transform, async_maybe_transform +from ....types.websocket_connection_options import WebSocketConnectionOptions +from ....types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides, is_recoverable_close +from ....types.machines.terminal_client_event import TerminalClientEvent +from ....types.machines.terminal_client_event_param import TerminalClientEventParam +from ....types.machines.terminal_server_event import TerminalServerEvent + +if TYPE_CHECKING: + from websockets.sync.client import ClientConnection as WebSocketConnection + from websockets.asyncio.client import ClientConnection as AsyncWebSocketConnection + from ...._client import Dedalus, AsyncDedalus + +__all__ = [ + "TerminalsResourceConnectionManager", + "AsyncTerminalsResourceConnectionManager", + "TerminalsResourceConnection", + "AsyncTerminalsResourceConnection", +] + +log: logging.Logger = logging.getLogger(__name__) + + +def _cookie_header(cookies: dict[str, str]) -> Headers: + """Serialize auth cookies into the WebSocket upgrade headers.""" + if not cookies: + return {} + + return {"Cookie": "; ".join(f"{key}={value}" for key, value in cookies.items())} + + +class TerminalsResourceConnection: + """Represents a live synchronous WebSocket connection.""" + + def __init__( + self, + connection: WebSocketConnection, + *, + make_ws: Callable[[Query, Headers], WebSocketConnection] | None = None, + on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, + max_retries: int = 5, + initial_delay: float = 0.5, + max_delay: float = 8.0, + extra_query: Query = {}, + extra_headers: Headers = {}, + send_queue: SendQueue | None = None, + ) -> None: + self._connection = connection + self._make_ws = make_ws + self._on_reconnecting = on_reconnecting + self._max_retries = max_retries + self._initial_delay = initial_delay + self._max_delay = max_delay + self._extra_query = extra_query + self._extra_headers = extra_headers + self._intentionally_closed = False + self._is_reconnecting = False + self._send_queue = send_queue or SendQueue() + self._event_handler_registry = EventHandlerRegistry(use_lock=True) + + def __iter__(self) -> Iterator[TerminalServerEvent]: + """Yield events until the connection closes.""" + from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError + + while True: + try: + yield self.recv() + except ConnectionClosedOK: + return + except ConnectionClosedError as exc: + if not self._reconnect(exc): + unsent = self._send_queue.drain() + if unsent: + raise WebSocketConnectionClosedError( + "WebSocket connection closed with unsent messages", + unsent_messages=unsent, + ) from exc + raise + + def recv(self) -> TerminalServerEvent: + """Receive and parse the next websocket message.""" + return self.parse_event(self.recv_bytes()) + + def recv_bytes(self) -> bytes: + """Receive the next websocket message as raw bytes.""" + message = self._connection.recv(decode=False) + log.debug("Received WebSocket message: %s", message) + return message + + def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + data = ( + event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) + if isinstance(event, BaseModel) + else json.dumps(maybe_transform(event, TerminalClientEventParam)) + ) + if self._is_reconnecting: + self._send_queue.enqueue(data) + return + try: + self._connection.send(data) + except Exception: + self._send_queue.enqueue(data) + raise + + def send_raw(self, data: bytes | str) -> None: + if self._is_reconnecting: + raw = data if isinstance(data, str) else data.decode("utf-8") + self._send_queue.enqueue(raw) + return + self._connection.send(data) + + def close(self, *, code: int = 1000, reason: str = "") -> None: + self._intentionally_closed = True + self._connection.close(code=code, reason=reason) + + def parse_event(self, data: str | bytes) -> TerminalServerEvent: + """Convert a raw websocket message into the generated server event type.""" + return cast( + TerminalServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, TerminalServerEvent)) + ) + + def _reconnect(self, exc: Exception) -> bool: + """Attempt to reconnect after a recoverable close exception.""" + if self._on_reconnecting is None or self._make_ws is None: + return False + + from websockets.exceptions import ConnectionClosedError + + close_code = 1006 + if isinstance(exc, ConnectionClosedError) and exc.rcvd is not None: + close_code = exc.rcvd.code + + if not is_recoverable_close(close_code): + return False + + self._is_reconnecting = True + for attempt in range(1, self._max_retries + 1): + base_delay = min(self._initial_delay * (2 ** (attempt - 1)), self._max_delay) + jitter = 0.75 + random.random() * 0.25 + delay = base_delay * jitter + + event = ReconnectingEvent( + attempt=attempt, + max_attempts=self._max_retries, + delay=delay, + close_code=close_code, + extra_query=self._extra_query, + extra_headers=self._extra_headers, + ) + try: + overrides = self._on_reconnecting(event) + except Exception: + self._is_reconnecting = False + return False + if overrides is not None and overrides.get("abort"): + self._is_reconnecting = False + return False + if overrides is not None: + if "extra_query" in overrides: + self._extra_query = overrides["extra_query"] + if "extra_headers" in overrides: + self._extra_headers = overrides["extra_headers"] + log.info( + "Reconnecting to WebSocket API (attempt %d/%d) after %.1fs delay", + attempt, + self._max_retries, + delay, + ) + time.sleep(delay) + if self._intentionally_closed: + self._is_reconnecting = False + return False + try: + self._connection = self._make_ws(self._extra_query, self._extra_headers) + log.info("Reconnected to WebSocket API") + self._flush_send_queue() + self._is_reconnecting = False + return True + except Exception: + pass + self._is_reconnecting = False + return False + + def _flush_send_queue(self) -> None: + """Send queued messages over the current connection after it opens or reconnects.""" + self._send_queue.flush_sync(lambda data: self._connection.send(data)) + + def on( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[TerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register an event handler, or return a decorator that registers one.""" + if handler is not None: + self._event_handler_registry.add(event_type, handler) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self._event_handler_registry.add(event_type, fn) + return fn + + return decorator + + def off(self, event_type: str, handler: Callable[..., Any]) -> TerminalsResourceConnection: + """Remove a previously registered event handler.""" + self._event_handler_registry.remove(event_type, handler) + return self + + def once( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[TerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register a one-time event handler.""" + if handler is not None: + self._event_handler_registry.add(event_type, handler, once=True) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self._event_handler_registry.add(event_type, fn, once=True) + return fn + + return decorator + + def dispatch_events(self) -> None: + """Dispatch incoming events to registered handlers until the connection closes.""" + for event in self: + event_type = event.type + specific = self._event_handler_registry.get_handlers(event_type) + generic = self._event_handler_registry.get_handlers("event") + + for handler in specific: + handler(event) + + for handler in generic: + handler(event) + + +class AsyncTerminalsResourceConnection: + """Represents a live asynchronous WebSocket connection.""" + + def __init__( + self, + connection: AsyncWebSocketConnection, + *, + make_ws: Callable[[Query, Headers], Awaitable[AsyncWebSocketConnection]] | None = None, + on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, + max_retries: int = 5, + initial_delay: float = 0.5, + max_delay: float = 8.0, + extra_query: Query = {}, + extra_headers: Headers = {}, + send_queue: SendQueue | None = None, + ) -> None: + self._connection = connection + self._make_ws = make_ws + self._on_reconnecting = on_reconnecting + self._max_retries = max_retries + self._initial_delay = initial_delay + self._max_delay = max_delay + self._extra_query = extra_query + self._extra_headers = extra_headers + self._intentionally_closed = False + self._is_reconnecting = False + self._send_queue = send_queue or SendQueue() + self._event_handler_registry = EventHandlerRegistry(use_lock=False) + + async def __aiter__(self) -> AsyncIterator[TerminalServerEvent]: + """Yield events until the connection closes.""" + from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError + + while True: + try: + yield await self.recv() + except ConnectionClosedOK: + return + except ConnectionClosedError as exc: + if not await self._reconnect(exc): + unsent = self._send_queue.drain() + if unsent: + raise WebSocketConnectionClosedError( + "WebSocket connection closed with unsent messages", + unsent_messages=unsent, + ) from exc + raise + + async def recv(self) -> TerminalServerEvent: + """Receive and parse the next websocket message.""" + return self.parse_event(await self.recv_bytes()) + + async def recv_bytes(self) -> bytes: + """Receive the next websocket message as raw bytes.""" + message = await self._connection.recv(decode=False) + log.debug("Received WebSocket message: %s", message) + return message + + async def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + data = ( + event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) + if isinstance(event, BaseModel) + else json.dumps(await async_maybe_transform(event, TerminalClientEventParam)) + ) + if self._is_reconnecting: + self._send_queue.enqueue(data) + return + try: + await self._connection.send(data) + except Exception: + self._send_queue.enqueue(data) + raise + + async def send_raw(self, data: bytes | str) -> None: + if self._is_reconnecting: + raw = data if isinstance(data, str) else data.decode("utf-8") + self._send_queue.enqueue(raw) + return + await self._connection.send(data) + + async def close(self, *, code: int = 1000, reason: str = "") -> None: + self._intentionally_closed = True + await self._connection.close(code=code, reason=reason) + + def parse_event(self, data: str | bytes) -> TerminalServerEvent: + """Convert a raw websocket message into the generated server event type.""" + return cast( + TerminalServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, TerminalServerEvent)) + ) + + async def _reconnect(self, exc: Exception) -> bool: + """Attempt to reconnect after a recoverable close exception.""" + import asyncio + + if self._on_reconnecting is None or self._make_ws is None: + return False + + from websockets.exceptions import ConnectionClosedError + + close_code = 1006 + if isinstance(exc, ConnectionClosedError) and exc.rcvd is not None: + close_code = exc.rcvd.code + + if not is_recoverable_close(close_code): + return False + + self._is_reconnecting = True + for attempt in range(1, self._max_retries + 1): + base_delay = min(self._initial_delay * (2 ** (attempt - 1)), self._max_delay) + jitter = 0.75 + random.random() * 0.25 + delay = base_delay * jitter + + event = ReconnectingEvent( + attempt=attempt, + max_attempts=self._max_retries, + delay=delay, + close_code=close_code, + extra_query=self._extra_query, + extra_headers=self._extra_headers, + ) + try: + overrides = self._on_reconnecting(event) + except Exception: + self._is_reconnecting = False + return False + if overrides is not None and overrides.get("abort"): + self._is_reconnecting = False + return False + if overrides is not None: + if "extra_query" in overrides: + self._extra_query = overrides["extra_query"] + if "extra_headers" in overrides: + self._extra_headers = overrides["extra_headers"] + log.info( + "Reconnecting to WebSocket API (attempt %d/%d) after %.1fs delay", + attempt, + self._max_retries, + delay, + ) + await asyncio.sleep(delay) + if self._intentionally_closed: + self._is_reconnecting = False + return False + try: + self._connection = await self._make_ws(self._extra_query, self._extra_headers) + log.info("Reconnected to WebSocket API") + await self._flush_send_queue() + self._is_reconnecting = False + return True + except Exception: + pass + self._is_reconnecting = False + return False + + async def _flush_send_queue(self) -> None: + """Send queued messages over the current connection after it opens or reconnects.""" + + async def _send(data: str) -> None: + await self._connection.send(data) + + await self._send_queue.flush_async(_send) + + def on( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[AsyncTerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register an event handler, or return a decorator that registers one.""" + if handler is not None: + self._event_handler_registry.add(event_type, handler) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self._event_handler_registry.add(event_type, fn) + return fn + + return decorator + + def off(self, event_type: str, handler: Callable[..., Any]) -> AsyncTerminalsResourceConnection: + """Remove a previously registered event handler.""" + self._event_handler_registry.remove(event_type, handler) + return self + + def once( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[AsyncTerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register a one-time event handler.""" + if handler is not None: + self._event_handler_registry.add(event_type, handler, once=True) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self._event_handler_registry.add(event_type, fn, once=True) + return fn + + return decorator + + async def dispatch_events(self) -> None: + """Dispatch incoming events to registered handlers until the connection closes.""" + import asyncio + + async for event in self: + event_type = event.type + specific = self._event_handler_registry.get_handlers(event_type) + generic = self._event_handler_registry.get_handlers("event") + + for handler in specific: + result = handler(event) + if asyncio.iscoroutine(result): + await result + + for handler in generic: + result = handler(event) + if asyncio.iscoroutine(result): + await result + + +class TerminalsResourceConnectionManager: + """Context-manager wrapper used by `connect()` to open a websocket lifecycle.""" + + def __init__( + self, + *, + client: Dedalus, + machine_id: str, + terminal_id: str, + extra_query: Query, + extra_headers: Headers, + websocket_connection_options: WebSocketConnectionOptions, + on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, + max_retries: int = 5, + initial_delay: float = 0.5, + max_delay: float = 8.0, + max_queue_size: int = 1_048_576, + ) -> None: + self.__client = client + self.__machine_id = machine_id + self.__terminal_id = terminal_id + self.__connection: TerminalsResourceConnection | None = None + self.__extra_query = extra_query + self.__extra_headers = extra_headers + self.__websocket_connection_options = websocket_connection_options + self.__on_reconnecting = on_reconnecting + self.__max_retries = max_retries + self.__initial_delay = initial_delay + self.__max_delay = max_delay + self.__send_queue = SendQueue(max_bytes=max_queue_size) + self.__event_handler_registry = EventHandlerRegistry(use_lock=True) + + def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + """Queue a message to send as soon as the websocket opens.""" + data = ( + event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) + if isinstance(event, BaseModel) + else json.dumps(maybe_transform(event, TerminalClientEventParam)) + ) + self.__send_queue.enqueue(data) + + def on( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[TerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register an event handler before the connection opens.""" + if handler is not None: + self.__event_handler_registry.add(event_type, handler) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self.__event_handler_registry.add(event_type, fn) + return fn + + return decorator + + def off(self, event_type: str, handler: Callable[..., Any]) -> TerminalsResourceConnectionManager: + """Remove a previously registered event handler.""" + self.__event_handler_registry.remove(event_type, handler) + return self + + def once( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[TerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register a one-time event handler before the connection opens.""" + if handler is not None: + self.__event_handler_registry.add(event_type, handler, once=True) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self.__event_handler_registry.add(event_type, fn, once=True) + return fn + + return decorator + + def __enter__(self) -> TerminalsResourceConnection: + ws = self._connect_ws(self.__extra_query, self.__extra_headers) + + self.__connection = TerminalsResourceConnection( + ws, + make_ws=self._connect_ws if self.__on_reconnecting is not None else None, + on_reconnecting=self.__on_reconnecting, + max_retries=self.__max_retries, + initial_delay=self.__initial_delay, + max_delay=self.__max_delay, + extra_query=self.__extra_query, + extra_headers=self.__extra_headers, + send_queue=self.__send_queue, + ) + + self.__event_handler_registry.merge_into(self.__connection._event_handler_registry) + self.__connection._flush_send_queue() + + return self.__connection + + enter = __enter__ + + def _connect_ws(self, extra_query: Query, extra_headers: Headers) -> WebSocketConnection: + try: + from websockets.sync.client import connect + except ImportError as exc: + raise DedalusError("You need to install `dedalus[websockets]` to use this method") from exc + + if not self.__machine_id: + raise ValueError(f"Expected a non-empty value for `machine_id` but received {self.__machine_id!r}") + if not self.__terminal_id: + raise ValueError(f"Expected a non-empty value for `terminal_id` but received {self.__terminal_id!r}") + url = self._prepare_url() + params = _merge_mappings( + { + **url.params, + **self.__client._auth_query({}), + **self.__client.default_query, + }, + extra_query, + ) + cookies = self.__client._auth_cookies({}) + headers = _merge_mappings( + { + **self.__client.auth_headers, + **_cookie_header(cookies), + }, + extra_headers, + ) + self.__client._validate_headers(headers, extra_headers, params, cookies) + url = url.copy_with(params=params) + log.debug("Connecting to %s", url) + if self.__websocket_connection_options: + log.debug("Connection options: %s", self.__websocket_connection_options) + + return connect( + str(url), + user_agent_header=self.__client.user_agent, + additional_headers=headers, + **self.__websocket_connection_options, + ) + + def _prepare_url(self) -> httpx.URL: + if self.__client.websocket_base_url is not None: + base_url = httpx.URL(self.__client.websocket_base_url) + else: + scheme = self.__client._base_url.scheme + ws_scheme = "ws" if scheme == "http" else "wss" + base_url = self.__client._base_url.copy_with(scheme=ws_scheme) + + merge_raw_path = base_url.raw_path.rstrip(b"/") + path_template( + "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", + machine_id=self.__machine_id, + terminal_id=self.__terminal_id, + ).encode("utf-8") + return base_url.copy_with(raw_path=merge_raw_path) + + def __exit__( + self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None + ) -> None: + if self.__connection is not None: + self.__connection.close() + + +class AsyncTerminalsResourceConnectionManager: + """Async context-manager wrapper used by `connect()` to open a websocket lifecycle.""" + + def __init__( + self, + *, + client: AsyncDedalus, + machine_id: str, + terminal_id: str, + extra_query: Query, + extra_headers: Headers, + websocket_connection_options: WebSocketConnectionOptions, + on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, + max_retries: int = 5, + initial_delay: float = 0.5, + max_delay: float = 8.0, + max_queue_size: int = 1_048_576, + ) -> None: + self.__client = client + self.__machine_id = machine_id + self.__terminal_id = terminal_id + self.__connection: AsyncTerminalsResourceConnection | None = None + self.__extra_query = extra_query + self.__extra_headers = extra_headers + self.__websocket_connection_options = websocket_connection_options + self.__on_reconnecting = on_reconnecting + self.__max_retries = max_retries + self.__initial_delay = initial_delay + self.__max_delay = max_delay + self.__send_queue = SendQueue(max_bytes=max_queue_size) + self.__event_handler_registry = EventHandlerRegistry(use_lock=False) + + def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + """Queue a message to send as soon as the websocket opens.""" + data = ( + event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) + if isinstance(event, BaseModel) + else json.dumps(maybe_transform(event, TerminalClientEventParam)) + ) + self.__send_queue.enqueue(data) + + def on( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[AsyncTerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register an event handler before the connection opens.""" + if handler is not None: + self.__event_handler_registry.add(event_type, handler) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self.__event_handler_registry.add(event_type, fn) + return fn + + return decorator + + def off(self, event_type: str, handler: Callable[..., Any]) -> AsyncTerminalsResourceConnectionManager: + """Remove a previously registered event handler.""" + self.__event_handler_registry.remove(event_type, handler) + return self + + def once( + self, event_type: str, handler: Callable[..., Any] | None = None + ) -> Union[AsyncTerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: + """Register a one-time event handler before the connection opens.""" + if handler is not None: + self.__event_handler_registry.add(event_type, handler, once=True) + return self + + def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: + self.__event_handler_registry.add(event_type, fn, once=True) + return fn + + return decorator + + async def __aenter__(self) -> AsyncTerminalsResourceConnection: + ws = await self._connect_ws(self.__extra_query, self.__extra_headers) + + self.__connection = AsyncTerminalsResourceConnection( + ws, + make_ws=self._connect_ws if self.__on_reconnecting is not None else None, + on_reconnecting=self.__on_reconnecting, + max_retries=self.__max_retries, + initial_delay=self.__initial_delay, + max_delay=self.__max_delay, + extra_query=self.__extra_query, + extra_headers=self.__extra_headers, + send_queue=self.__send_queue, + ) + + self.__event_handler_registry.merge_into(self.__connection._event_handler_registry) + await self.__connection._flush_send_queue() + + return self.__connection + + enter = __aenter__ + + async def _connect_ws(self, extra_query: Query, extra_headers: Headers) -> AsyncWebSocketConnection: + try: + from websockets.asyncio.client import connect + except ImportError as exc: + raise DedalusError("You need to install `dedalus[websockets]` to use this method") from exc + + if not self.__machine_id: + raise ValueError(f"Expected a non-empty value for `machine_id` but received {self.__machine_id!r}") + if not self.__terminal_id: + raise ValueError(f"Expected a non-empty value for `terminal_id` but received {self.__terminal_id!r}") + url = self._prepare_url() + params = _merge_mappings( + { + **url.params, + **self.__client._auth_query({}), + **self.__client.default_query, + }, + extra_query, + ) + cookies = self.__client._auth_cookies({}) + headers = _merge_mappings( + { + **self.__client.auth_headers, + **_cookie_header(cookies), + }, + extra_headers, + ) + self.__client._validate_headers(headers, extra_headers, params, cookies) + url = url.copy_with(params=params) + log.debug("Connecting to %s", url) + if self.__websocket_connection_options: + log.debug("Connection options: %s", self.__websocket_connection_options) + + return await connect( + str(url), + user_agent_header=self.__client.user_agent, + additional_headers=headers, + **self.__websocket_connection_options, + ) + + def _prepare_url(self) -> httpx.URL: + if self.__client.websocket_base_url is not None: + base_url = httpx.URL(self.__client.websocket_base_url) + else: + scheme = self.__client._base_url.scheme + ws_scheme = "ws" if scheme == "http" else "wss" + base_url = self.__client._base_url.copy_with(scheme=ws_scheme) + + merge_raw_path = base_url.raw_path.rstrip(b"/") + path_template( + "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", + machine_id=self.__machine_id, + terminal_id=self.__terminal_id, + ).encode("utf-8") + return base_url.copy_with(raw_path=merge_raw_path) + + async def __aexit__( + self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None + ) -> None: + if self.__connection is not None: + await self.__connection.close() diff --git a/src/dedalus_sdk/resources/networks.py b/src/dedalus_sdk/resources/networks.py new file mode 100644 index 0000000..fc9b768 --- /dev/null +++ b/src/dedalus_sdk/resources/networks.py @@ -0,0 +1,164 @@ +# File generated from our OpenAPI spec by Scalar. See README.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, strip_not_given +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.network import Network + +__all__ = ["NetworksResource", "AsyncNetworksResource"] + + +class NetworksResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> NetworksResourceWithRawResponse: + return NetworksResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> NetworksResourceWithStreamingResponse: + return NetworksResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + network_id: str, + x_dedalus_org_id: 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, + ) -> Network: + """ + Get network details + + Args: + network_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Network: OK + + Example: + ```python + network = client.networks.retrieve( + network_id="networkID", + ) + ``` + """ + if network_id is None or (isinstance(network_id, str) and not network_id): + raise ValueError(f"Expected a non-empty value for `network_id` but received {network_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return self._get( + path_template("/v1/networks/{network_id}", **{"network_id": network_id}), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Network, + ) + + +class AsyncNetworksResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncNetworksResourceWithRawResponse: + return AsyncNetworksResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncNetworksResourceWithStreamingResponse: + return AsyncNetworksResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + network_id: str, + x_dedalus_org_id: 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, + ) -> Network: + """ + Get network details + + Args: + network_id: Path parameter. + x_dedalus_org_id: Header parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Network: OK + + Example: + ```python + network = await client.networks.retrieve( + network_id="networkID", + ) + ``` + """ + if network_id is None or (isinstance(network_id, str) and not network_id): + raise ValueError(f"Expected a non-empty value for `network_id` but received {network_id!r}") + extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} + return await self._get( + path_template("/v1/networks/{network_id}", **{"network_id": network_id}), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Network, + ) + + +class NetworksResourceWithRawResponse: + def __init__(self, networks: NetworksResource) -> None: + self._networks = networks + + self.retrieve = to_raw_response_wrapper( + networks.retrieve, + ) + + +class AsyncNetworksResourceWithRawResponse: + def __init__(self, networks: AsyncNetworksResource) -> None: + self._networks = networks + + self.retrieve = async_to_raw_response_wrapper( + networks.retrieve, + ) + + +class NetworksResourceWithStreamingResponse: + def __init__(self, networks: NetworksResource) -> None: + self._networks = networks + + self.retrieve = to_streamed_response_wrapper( + networks.retrieve, + ) + + +class AsyncNetworksResourceWithStreamingResponse: + def __init__(self, networks: AsyncNetworksResource) -> None: + self._networks = networks + + self.retrieve = async_to_streamed_response_wrapper( + networks.retrieve, + ) diff --git a/src/dedalus_sdk/resources/usage.py b/src/dedalus_sdk/resources/usage.py new file mode 100644 index 0000000..02b235f --- /dev/null +++ b/src/dedalus_sdk/resources/usage.py @@ -0,0 +1,393 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import httpx + +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.org_usage import OrgUsage +from ..types import usage_retrieve_params, usage_machine_compute_params, usage_machine_storage_params +from ..types.machine_compute_usage import MachineComputeUsage +from ..types.machine_storage_usage import MachineStorageUsage + +__all__ = ["UsageResource", "AsyncUsageResource"] + + +class UsageResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> UsageResourceWithRawResponse: + return UsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> UsageResourceWithStreamingResponse: + return UsageResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + 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 usage summary + + Args: + period_start: Billing period start (YYYY-MM-DD). Defaults to first of current month. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + OrgUsage: OK + + Example: + ```python + usage = client.usage.retrieve() + ``` + """ + return self._get( + "/v1/usage", + 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 machine_compute( + self, + *, + period_start: str | Omit = omit, + period_end: str | Omit = omit, + machine_id: str | Omit = omit, + granularity: 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, + ) -> MachineComputeUsage: + """ + List machine compute usage breakdown + + Args: + period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. + period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. + machine_id: Optional machine ID filter. + granularity: Usage breakdown granularity: hour or day. Defaults to hour. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineComputeUsage: OK + + Example: + ```python + usage = client.usage.machine_compute() + ``` + """ + return self._get( + "/v1/usage/machines/compute", + 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, + "period_end": period_end, + "machine_id": machine_id, + "granularity": granularity, + }, + usage_machine_compute_params.UsageMachineComputeParams, + ), + ), + cast_to=MachineComputeUsage, + ) + + def machine_storage( + self, + *, + period_start: str | Omit = omit, + period_end: str | Omit = omit, + machine_id: 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 breakdown + + Args: + period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. + period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. + machine_id: Optional machine ID filter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineStorageUsage: OK + + Example: + ```python + usage = client.usage.machine_storage() + ``` + """ + return self._get( + "/v1/usage/machines/storage", + 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, "period_end": period_end, "machine_id": machine_id}, + usage_machine_storage_params.UsageMachineStorageParams, + ), + ), + cast_to=MachineStorageUsage, + ) + + +class AsyncUsageResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: + return AsyncUsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: + return AsyncUsageResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + 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 usage summary + + Args: + period_start: Billing period start (YYYY-MM-DD). Defaults to first of current month. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + OrgUsage: OK + + Example: + ```python + usage = await client.usage.retrieve() + ``` + """ + return await self._get( + "/v1/usage", + 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 machine_compute( + self, + *, + period_start: str | Omit = omit, + period_end: str | Omit = omit, + machine_id: str | Omit = omit, + granularity: 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, + ) -> MachineComputeUsage: + """ + List machine compute usage breakdown + + Args: + period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. + period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. + machine_id: Optional machine ID filter. + granularity: Usage breakdown granularity: hour or day. Defaults to hour. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineComputeUsage: OK + + Example: + ```python + usage = await client.usage.machine_compute() + ``` + """ + return await self._get( + "/v1/usage/machines/compute", + 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, + "period_end": period_end, + "machine_id": machine_id, + "granularity": granularity, + }, + usage_machine_compute_params.UsageMachineComputeParams, + ), + ), + cast_to=MachineComputeUsage, + ) + + async def machine_storage( + self, + *, + period_start: str | Omit = omit, + period_end: str | Omit = omit, + machine_id: 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 breakdown + + Args: + period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. + period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. + machine_id: Optional machine ID filter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + MachineStorageUsage: OK + + Example: + ```python + usage = await client.usage.machine_storage() + ``` + """ + return await self._get( + "/v1/usage/machines/storage", + 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, "period_end": period_end, "machine_id": machine_id}, + usage_machine_storage_params.UsageMachineStorageParams, + ), + ), + cast_to=MachineStorageUsage, + ) + + +class UsageResourceWithRawResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + self.retrieve = to_raw_response_wrapper( + usage.retrieve, + ) + self.machine_compute = to_raw_response_wrapper( + usage.machine_compute, + ) + self.machine_storage = to_raw_response_wrapper( + usage.machine_storage, + ) + + +class AsyncUsageResourceWithRawResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + self.retrieve = async_to_raw_response_wrapper( + usage.retrieve, + ) + self.machine_compute = async_to_raw_response_wrapper( + usage.machine_compute, + ) + self.machine_storage = async_to_raw_response_wrapper( + usage.machine_storage, + ) + + +class UsageResourceWithStreamingResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + self.retrieve = to_streamed_response_wrapper( + usage.retrieve, + ) + self.machine_compute = to_streamed_response_wrapper( + usage.machine_compute, + ) + self.machine_storage = to_streamed_response_wrapper( + usage.machine_storage, + ) + + +class AsyncUsageResourceWithStreamingResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + self.retrieve = async_to_streamed_response_wrapper( + usage.retrieve, + ) + self.machine_compute = async_to_streamed_response_wrapper( + usage.machine_compute, + ) + self.machine_storage = async_to_streamed_response_wrapper( + usage.machine_storage, + ) diff --git a/src/dedalus_sdk/types/__init__.py b/src/dedalus_sdk/types/__init__.py index 6c1da62..ab76b6d 100644 --- a/src/dedalus_sdk/types/__init__.py +++ b/src/dedalus_sdk/types/__init__.py @@ -1,12 +1,27 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations from .machine import Machine as Machine -from .machine_list import MachineList as MachineList from .lifecycle_status import LifecycleStatus as LifecycleStatus +from .machine_compute_usage import MachineComputeUsage as MachineComputeUsage +from .machine_compute_usage_row import MachineComputeUsageRow as MachineComputeUsageRow from .machine_list_item import MachineListItem as MachineListItem +from .machine_list import MachineList as MachineList +from .machine_storage_usage import MachineStorageUsage as MachineStorageUsage +from .machine_storage_usage_row import MachineStorageUsageRow as MachineStorageUsageRow +from .network_gateway import NetworkGateway as NetworkGateway +from .network import Network as Network +from .org_usage import OrgUsage as OrgUsage from .machine_list_params import MachineListParams as MachineListParams from .machine_create_params import MachineCreateParams as MachineCreateParams -from .machine_update_params import MachineUpdateParams as MachineUpdateParams from .machine_retrieve_response import MachineRetrieveResponse as MachineRetrieveResponse +from .machine_update_params import MachineUpdateParams as MachineUpdateParams +from .usage_retrieve_params import UsageRetrieveParams as UsageRetrieveParams +from .usage_machine_compute_params import UsageMachineComputeParams as UsageMachineComputeParams +from .usage_machine_storage_params import UsageMachineStorageParams as UsageMachineStorageParams +from .websocket_connection_options import WebSocketConnectionOptions as WebSocketConnectionOptions +from .websocket_reconnection import ( + ReconnectingEvent as ReconnectingEvent, + ReconnectingOverrides as ReconnectingOverrides, +) diff --git a/src/dedalus_sdk/types/lifecycle_status.py b/src/dedalus_sdk/types/lifecycle_status.py index 463b23f..fddc07a 100644 --- a/src/dedalus_sdk/types/lifecycle_status.py +++ b/src/dedalus_sdk/types/lifecycle_status.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import Optional from datetime import datetime @@ -10,6 +10,8 @@ class LifecycleStatus(BaseModel): + last_error: Optional[str] = None + last_progress_at: datetime last_transition_at: datetime @@ -31,5 +33,3 @@ class LifecycleStatus(BaseModel): retryable: bool revision: str - - last_error: Optional[str] = None diff --git a/src/dedalus_sdk/types/machine.py b/src/dedalus_sdk/types/machine.py index cc707a2..be05a3d 100644 --- a/src/dedalus_sdk/types/machine.py +++ b/src/dedalus_sdk/types/machine.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing_extensions import Literal diff --git a/src/dedalus_sdk/types/machine_compute_usage.py b/src/dedalus_sdk/types/machine_compute_usage.py new file mode 100644 index 0000000..e6e5d82 --- /dev/null +++ b/src/dedalus_sdk/types/machine_compute_usage.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import List, Optional +from datetime import datetime + +from .._models import BaseModel + +from .machine_compute_usage_row import MachineComputeUsageRow + +__all__ = ["MachineComputeUsage"] + + +class MachineComputeUsage(BaseModel): + granularity: str + """Usage breakdown granularity used for rows: hour or day.""" + + period_end: datetime + """Exclusive usage period end.""" + + period_start: datetime + """Inclusive usage period start.""" + + rows: Optional[List[MachineComputeUsageRow]] = None + """Machine-level compute usage breakdown rows.""" diff --git a/src/dedalus_sdk/types/machine_compute_usage_row.py b/src/dedalus_sdk/types/machine_compute_usage_row.py new file mode 100644 index 0000000..3df4d33 --- /dev/null +++ b/src/dedalus_sdk/types/machine_compute_usage_row.py @@ -0,0 +1,52 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import List, Optional +from datetime import datetime + +from .._models import BaseModel + +__all__ = ["MachineComputeUsageRow"] + + +class MachineComputeUsageRow(BaseModel): + awake_seconds: int + """Machine-awake seconds in this bucket.""" + + bucket_end: datetime + """Exclusive usage bucket end.""" + + bucket_start: datetime + """Inclusive usage bucket start.""" + + cpu_millicore_seconds: int + """Requested vCPU millicores multiplied by guest-owned active CPU seconds.""" + + last_window_end: datetime + """Latest raw window_end represented by this row.""" + + latest_meter_emitted_at: Optional[datetime] = None + """Latest meter emission timestamp for linked org buckets, when emitted.""" + + machine_id: str + """Machine identifier.""" + + memory_mib_seconds: int + """Requested memory MiB multiplied by running allocation seconds.""" + + org_metering_bucket_ids: Optional[List[str]] = None + """Org compute bucket IDs this 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.""" + + window_count: int + """Raw metering events compacted into this row.""" diff --git a/src/dedalus_sdk/types/machine_create_params.py b/src/dedalus_sdk/types/machine_create_params.py index 1a39a10..9f724f5 100644 --- a/src/dedalus_sdk/types/machine_create_params.py +++ b/src/dedalus_sdk/types/machine_create_params.py @@ -1,19 +1,17 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo __all__ = ["MachineCreateParams"] class MachineCreateParams(TypedDict, total=False): autosleep: str - """Idle window before autosleep. - - Accepts fixed duration units like 30s, 30m, 2h, 7d3h4s, or 1w3d, raw seconds - ("1800"), or never to disable. - """ + """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.""" @@ -23,3 +21,5 @@ class MachineCreateParams(TypedDict, total=False): vcpu: float """CPU in vCPUs.""" + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machine_list.py b/src/dedalus_sdk/types/machine_list.py index d809935..bdd123c 100644 --- a/src/dedalus_sdk/types/machine_list.py +++ b/src/dedalus_sdk/types/machine_list.py @@ -1,8 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import List, Optional from .._models import BaseModel + from .machine_list_item import MachineListItem __all__ = ["MachineList"] diff --git a/src/dedalus_sdk/types/machine_list_item.py b/src/dedalus_sdk/types/machine_list_item.py index 440d90a..51242ac 100644 --- a/src/dedalus_sdk/types/machine_list_item.py +++ b/src/dedalus_sdk/types/machine_list_item.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from datetime import datetime from typing_extensions import Literal diff --git a/src/dedalus_sdk/types/machine_list_params.py b/src/dedalus_sdk/types/machine_list_params.py index 2676797..a17dbbc 100644 --- a/src/dedalus_sdk/types/machine_list_params.py +++ b/src/dedalus_sdk/types/machine_list_params.py @@ -1,13 +1,17 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo __all__ = ["MachineListParams"] class MachineListParams(TypedDict, total=False): + limit: int + cursor: str - limit: int + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machine_retrieve_response.py b/src/dedalus_sdk/types/machine_retrieve_response.py index 009a023..4687668 100644 --- a/src/dedalus_sdk/types/machine_retrieve_response.py +++ b/src/dedalus_sdk/types/machine_retrieve_response.py @@ -1,8 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing_extensions import Literal from .._models import BaseModel + from .lifecycle_status import LifecycleStatus __all__ = ["MachineRetrieveResponse"] diff --git a/src/dedalus_sdk/types/machine_storage_usage.py b/src/dedalus_sdk/types/machine_storage_usage.py new file mode 100644 index 0000000..5e26335 --- /dev/null +++ b/src/dedalus_sdk/types/machine_storage_usage.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import List, Optional +from datetime import datetime + +from .._models import BaseModel + +from .machine_storage_usage_row import MachineStorageUsageRow + +__all__ = ["MachineStorageUsage"] + + +class MachineStorageUsage(BaseModel): + period_end: datetime + """Exclusive usage period end.""" + + period_start: datetime + """Inclusive usage period start.""" + + rows: Optional[List[MachineStorageUsageRow]] = None + """Machine-level storage usage breakdown rows.""" diff --git a/src/dedalus_sdk/types/machine_storage_usage_row.py b/src/dedalus_sdk/types/machine_storage_usage_row.py new file mode 100644 index 0000000..c69ee09 --- /dev/null +++ b/src/dedalus_sdk/types/machine_storage_usage_row.py @@ -0,0 +1,31 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Optional +from datetime import datetime + +from .._models import BaseModel + +__all__ = ["MachineStorageUsageRow"] + + +class MachineStorageUsageRow(BaseModel): + bucket_end: datetime + """Exclusive usage bucket end.""" + + bucket_start: datetime + """Inclusive usage bucket start.""" + + latest_meter_emitted_at: Optional[datetime] = None + """Latest meter emission timestamp for the linked org bucket, when emitted.""" + + 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 row contributes to.""" + + storage_mib_seconds: int + """Allocated logical MiB-seconds for this machine.""" diff --git a/src/dedalus_sdk/types/machine_update_params.py b/src/dedalus_sdk/types/machine_update_params.py index 90f5a35..3a5abd3 100644 --- a/src/dedalus_sdk/types/machine_update_params.py +++ b/src/dedalus_sdk/types/machine_update_params.py @@ -1,8 +1,10 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Annotated, Required, TypedDict + +from .._utils import PropertyInfo __all__ = ["MachineUpdateParams"] @@ -11,11 +13,7 @@ class MachineUpdateParams(TypedDict, total=False): machine_id: Required[str] autosleep: str - """Idle window before autosleep. - - Accepts fixed duration units like 30s, 30m, 2h, 7d3h4s, or 1w3d, raw seconds - ("1800"), or never to disable. - """ + """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.""" @@ -25,3 +23,5 @@ class MachineUpdateParams(TypedDict, total=False): vcpu: float """CPU in vCPUs.""" + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/__init__.py b/src/dedalus_sdk/types/machines/__init__.py index bf1af89..f4d1a71 100644 --- a/src/dedalus_sdk/types/machines/__init__.py +++ b/src/dedalus_sdk/types/machines/__init__.py @@ -1,19 +1,41 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from .execution import Execution as Execution -from .ssh_session import SSHSession as SSHSession +from .artifact_list import ArtifactList as ArtifactList from .artifact_ref import ArtifactRef as ArtifactRef -from .execution_list import ExecutionList as ExecutionList -from .ssh_connection import SSHConnection as SSHConnection -from .ssh_host_trust import SSHHostTrust as SSHHostTrust +from .artifact import Artifact as Artifact from .execution_event import ExecutionEvent as ExecutionEvent -from .ssh_list_params import SSHListParams as SSHListParams from .execution_events import ExecutionEvents as ExecutionEvents +from .execution_list import ExecutionList as ExecutionList from .execution_output import ExecutionOutput as ExecutionOutput +from .execution import Execution as Execution +from .machine_network import MachineNetwork as MachineNetwork +from .port_list import PortList as PortList +from .port import Port as Port +from .ssh_connection import SSHConnection as SSHConnection +from .ssh_host_trust import SSHHostTrust as SSHHostTrust from .ssh_session_list import SSHSessionList as SSHSessionList +from .ssh_session import SSHSession as SSHSession +from .terminal_client_event import TerminalClientEvent as TerminalClientEvent +from .terminal_closed_event import TerminalClosedEvent as TerminalClosedEvent +from .terminal_error_event import TerminalErrorEvent as TerminalErrorEvent +from .terminal_input_event import TerminalInputEvent as TerminalInputEvent +from .terminal_list import TerminalList as TerminalList +from .terminal_output_event import TerminalOutputEvent as TerminalOutputEvent +from .terminal_resize_event import TerminalResizeEvent as TerminalResizeEvent +from .terminal import Terminal as Terminal +from .terminal_server_event import TerminalServerEvent as TerminalServerEvent +from .artifact_list_params import ArtifactListParams as ArtifactListParams +from .port_list_params import PortListParams as PortListParams +from .port_create_params import PortCreateParams as PortCreateParams +from .ssh_list_params import SSHListParams as SSHListParams from .ssh_create_params import SSHCreateParams as SSHCreateParams from .execution_list_params import ExecutionListParams as ExecutionListParams from .execution_create_params import ExecutionCreateParams as ExecutionCreateParams from .execution_events_params import ExecutionEventsParams as ExecutionEventsParams +from .terminal_list_params import TerminalListParams as TerminalListParams +from .terminal_create_params import TerminalCreateParams as TerminalCreateParams +from .terminal_input_event_param import TerminalInputEventParam as TerminalInputEventParam +from .terminal_resize_event_param import TerminalResizeEventParam as TerminalResizeEventParam +from .terminal_client_event_param import TerminalClientEventParam as TerminalClientEventParam diff --git a/src/dedalus_sdk/types/machines/artifact.py b/src/dedalus_sdk/types/machines/artifact.py new file mode 100644 index 0000000..7d5fa86 --- /dev/null +++ b/src/dedalus_sdk/types/machines/artifact.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Optional +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["Artifact"] + + +class Artifact(BaseModel): + artifact_id: str + + created_at: datetime + + download_url: Optional[str] = None + + execution_id: Optional[str] = None + + expires_at: Optional[datetime] = None + + machine_id: str + + mime_type: Optional[str] = None + + name: str + + sha256: Optional[str] = None + + size_bytes: int diff --git a/src/dedalus_sdk/types/machines/artifact_list.py b/src/dedalus_sdk/types/machines/artifact_list.py new file mode 100644 index 0000000..1bd78df --- /dev/null +++ b/src/dedalus_sdk/types/machines/artifact_list.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +from .artifact import Artifact + +__all__ = ["ArtifactList"] + + +class ArtifactList(BaseModel): + items: Optional[List[Artifact]] = None + + next_cursor: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/artifact_list_params.py b/src/dedalus_sdk/types/machines/artifact_list_params.py new file mode 100644 index 0000000..c53be52 --- /dev/null +++ b/src/dedalus_sdk/types/machines/artifact_list_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ArtifactListParams"] + + +class ArtifactListParams(TypedDict, total=False): + machine_id: Required[str] + + limit: int + + cursor: str + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/artifact_ref.py b/src/dedalus_sdk/types/machines/artifact_ref.py index 4f31735..5e70a9e 100644 --- a/src/dedalus_sdk/types/machines/artifact_ref.py +++ b/src/dedalus_sdk/types/machines/artifact_ref.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from ..._models import BaseModel diff --git a/src/dedalus_sdk/types/machines/execution.py b/src/dedalus_sdk/types/machines/execution.py index 087d684..b08f14b 100644 --- a/src/dedalus_sdk/types/machines/execution.py +++ b/src/dedalus_sdk/types/machines/execution.py @@ -1,30 +1,25 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel + from .artifact_ref import ArtifactRef __all__ = ["Execution"] class Execution(BaseModel): - command: Optional[List[str]] = None - - created_at: datetime - - execution_id: str - - machine_id: str - - status: Literal["wake_in_progress", "queued", "running", "succeeded", "failed", "cancelled", "expired"] - artifacts: Optional[List[ArtifactRef]] = None + command: Optional[List[str]] = None + completed_at: Optional[datetime] = None + created_at: datetime + cwd: Optional[str] = None env_keys: Optional[List[str]] = None @@ -33,16 +28,22 @@ class Execution(BaseModel): error_message: Optional[str] = None + execution_id: str + exit_code: Optional[int] = None expires_at: Optional[datetime] = None + machine_id: str + retry_after_ms: Optional[int] = None signal: Optional[int] = None started_at: Optional[datetime] = None + status: Literal["wake_in_progress", "queued", "running", "succeeded", "failed", "cancelled", "expired"] + stderr_bytes: Optional[int] = None stderr_truncated: Optional[bool] = None diff --git a/src/dedalus_sdk/types/machines/execution_create_params.py b/src/dedalus_sdk/types/machines/execution_create_params.py index 293f839..55c67ed 100644 --- a/src/dedalus_sdk/types/machines/execution_create_params.py +++ b/src/dedalus_sdk/types/machines/execution_create_params.py @@ -1,12 +1,13 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations from typing import Dict, Optional -from typing_extensions import Required, TypedDict - +from typing_extensions import Annotated, Required, TypedDict from ..._types import SequenceNotStr +from ..._utils import PropertyInfo + __all__ = ["ExecutionCreateParams"] @@ -22,3 +23,5 @@ class ExecutionCreateParams(TypedDict, total=False): stdin: str timeout_ms: int + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/execution_event.py b/src/dedalus_sdk/types/machines/execution_event.py index 816c3b3..e0ca67b 100644 --- a/src/dedalus_sdk/types/machines/execution_event.py +++ b/src/dedalus_sdk/types/machines/execution_event.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import Optional from datetime import datetime @@ -12,10 +12,6 @@ class ExecutionEvent(BaseModel): at: datetime - sequence: int - - type: Literal["lifecycle", "stdout", "stderr"] - chunk: Optional[str] = None error_code: Optional[str] = None @@ -24,8 +20,12 @@ class ExecutionEvent(BaseModel): exit_code: Optional[int] = None + sequence: int + signal: Optional[int] = None status: Optional[ Literal["wake_in_progress", "queued", "running", "succeeded", "failed", "cancelled", "expired"] ] = None + + type: Literal["lifecycle", "stdout", "stderr"] diff --git a/src/dedalus_sdk/types/machines/execution_events.py b/src/dedalus_sdk/types/machines/execution_events.py index edb7a28..1b1f8df 100644 --- a/src/dedalus_sdk/types/machines/execution_events.py +++ b/src/dedalus_sdk/types/machines/execution_events.py @@ -1,8 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import List, Optional from ..._models import BaseModel + from .execution_event import ExecutionEvent __all__ = ["ExecutionEvents"] diff --git a/src/dedalus_sdk/types/machines/execution_events_params.py b/src/dedalus_sdk/types/machines/execution_events_params.py index f2ec158..2dc6e7d 100644 --- a/src/dedalus_sdk/types/machines/execution_events_params.py +++ b/src/dedalus_sdk/types/machines/execution_events_params.py @@ -1,8 +1,10 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo __all__ = ["ExecutionEventsParams"] @@ -12,6 +14,8 @@ class ExecutionEventsParams(TypedDict, total=False): execution_id: Required[str] + limit: int + cursor: str - limit: int + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/execution_list.py b/src/dedalus_sdk/types/machines/execution_list.py index 13d557c..6a80d05 100644 --- a/src/dedalus_sdk/types/machines/execution_list.py +++ b/src/dedalus_sdk/types/machines/execution_list.py @@ -1,8 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import List, Optional from ..._models import BaseModel + from .execution import Execution __all__ = ["ExecutionList"] diff --git a/src/dedalus_sdk/types/machines/execution_list_params.py b/src/dedalus_sdk/types/machines/execution_list_params.py index 9bbbd28..264839b 100644 --- a/src/dedalus_sdk/types/machines/execution_list_params.py +++ b/src/dedalus_sdk/types/machines/execution_list_params.py @@ -1,8 +1,10 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo __all__ = ["ExecutionListParams"] @@ -10,6 +12,8 @@ class ExecutionListParams(TypedDict, total=False): machine_id: Required[str] + limit: int + cursor: str - limit: int + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/execution_output.py b/src/dedalus_sdk/types/machines/execution_output.py index 41e9285..37352f9 100644 --- a/src/dedalus_sdk/types/machines/execution_output.py +++ b/src/dedalus_sdk/types/machines/execution_output.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import Optional diff --git a/src/dedalus_sdk/types/machines/machine_network.py b/src/dedalus_sdk/types/machines/machine_network.py new file mode 100644 index 0000000..0b4b434 --- /dev/null +++ b/src/dedalus_sdk/types/machines/machine_network.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from ..._models import BaseModel + +__all__ = ["MachineNetwork"] + + +class MachineNetwork(BaseModel): + hostname: str + + machine_id: str + + network_id: str + + network_name: str + + private_ipv4: str + + private_ipv6: str diff --git a/src/dedalus_sdk/types/machines/port.py b/src/dedalus_sdk/types/machines/port.py new file mode 100644 index 0000000..909b745 --- /dev/null +++ b/src/dedalus_sdk/types/machines/port.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["Port"] + + +class Port(BaseModel): + created_at: datetime + + error_code: Optional[str] = None + + error_message: Optional[str] = None + + expires_at: Optional[datetime] = None + + machine_id: str + + port: int + + port_id: str + + protocol: Optional[Literal["http", "https"]] = None + + ready_at: Optional[datetime] = None + + retry_after_ms: Optional[int] = None + + status: Literal["wake_in_progress", "ready", "closed", "expired", "failed"] + + url: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/port_create_params.py b/src/dedalus_sdk/types/machines/port_create_params.py new file mode 100644 index 0000000..c5ac5d2 --- /dev/null +++ b/src/dedalus_sdk/types/machines/port_create_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, Literal, Required, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["PortCreateParams"] + + +class PortCreateParams(TypedDict, total=False): + machine_id: Required[str] + + port: Required[int] + + protocol: Literal["http", "https"] + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/port_list.py b/src/dedalus_sdk/types/machines/port_list.py new file mode 100644 index 0000000..7fc5b82 --- /dev/null +++ b/src/dedalus_sdk/types/machines/port_list.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +from .port import Port + +__all__ = ["PortList"] + + +class PortList(BaseModel): + items: Optional[List[Port]] = None + + next_cursor: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/port_list_params.py b/src/dedalus_sdk/types/machines/port_list_params.py new file mode 100644 index 0000000..60b8de0 --- /dev/null +++ b/src/dedalus_sdk/types/machines/port_list_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["PortListParams"] + + +class PortListParams(TypedDict, total=False): + machine_id: Required[str] + + limit: int + + cursor: str + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/ssh_connection.py b/src/dedalus_sdk/types/machines/ssh_connection.py index 61919bf..eb6a932 100644 --- a/src/dedalus_sdk/types/machines/ssh_connection.py +++ b/src/dedalus_sdk/types/machines/ssh_connection.py @@ -1,8 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import Optional from ..._models import BaseModel + from .ssh_host_trust import SSHHostTrust __all__ = ["SSHConnection"] @@ -11,10 +12,10 @@ class SSHConnection(BaseModel): endpoint: str + host_trust: Optional[SSHHostTrust] = None + port: int ssh_username: str - host_trust: Optional[SSHHostTrust] = None - user_certificate: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/ssh_create_params.py b/src/dedalus_sdk/types/machines/ssh_create_params.py index 8d1a164..46cebf0 100644 --- a/src/dedalus_sdk/types/machines/ssh_create_params.py +++ b/src/dedalus_sdk/types/machines/ssh_create_params.py @@ -1,8 +1,10 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo __all__ = ["SSHCreateParams"] @@ -11,3 +13,5 @@ class SSHCreateParams(TypedDict, total=False): machine_id: Required[str] public_key: Required[str] + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/ssh_host_trust.py b/src/dedalus_sdk/types/machines/ssh_host_trust.py index a7c2db1..0cbacaa 100644 --- a/src/dedalus_sdk/types/machines/ssh_host_trust.py +++ b/src/dedalus_sdk/types/machines/ssh_host_trust.py @@ -1,4 +1,4 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing_extensions import Literal diff --git a/src/dedalus_sdk/types/machines/ssh_list_params.py b/src/dedalus_sdk/types/machines/ssh_list_params.py index 81a285e..a3f4bd5 100644 --- a/src/dedalus_sdk/types/machines/ssh_list_params.py +++ b/src/dedalus_sdk/types/machines/ssh_list_params.py @@ -1,8 +1,10 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo __all__ = ["SSHListParams"] @@ -10,6 +12,8 @@ class SSHListParams(TypedDict, total=False): machine_id: Required[str] + limit: int + cursor: str - limit: int + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/ssh_session.py b/src/dedalus_sdk/types/machines/ssh_session.py index d746518..7eacfd3 100644 --- a/src/dedalus_sdk/types/machines/ssh_session.py +++ b/src/dedalus_sdk/types/machines/ssh_session.py @@ -1,32 +1,33 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel + from .ssh_connection import SSHConnection __all__ = ["SSHSession"] class SSHSession(BaseModel): - created_at: datetime - - machine_id: str - - session_id: str - - status: Literal["wake_in_progress", "ready", "closed", "expired", "failed"] - connection: Optional[SSHConnection] = None + created_at: datetime + error_code: Optional[str] = None error_message: Optional[str] = None expires_at: Optional[datetime] = None + machine_id: str + ready_at: Optional[datetime] = None retry_after_ms: Optional[int] = None + + session_id: str + + status: Literal["wake_in_progress", "ready", "closed", "expired", "failed"] diff --git a/src/dedalus_sdk/types/machines/ssh_session_list.py b/src/dedalus_sdk/types/machines/ssh_session_list.py index 7df0fad..1c9a657 100644 --- a/src/dedalus_sdk/types/machines/ssh_session_list.py +++ b/src/dedalus_sdk/types/machines/ssh_session_list.py @@ -1,8 +1,9 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +# File generated from our OpenAPI spec by Scalar. See README.md for details. from typing import List, Optional from ..._models import BaseModel + from .ssh_session import SSHSession __all__ = ["SSHSessionList"] diff --git a/src/dedalus_sdk/types/machines/terminal.py b/src/dedalus_sdk/types/machines/terminal.py new file mode 100644 index 0000000..c86ceb9 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["Terminal"] + + +class Terminal(BaseModel): + created_at: datetime + + error_code: Optional[str] = None + + error_message: Optional[str] = None + + expires_at: Optional[datetime] = None + + height: int + + machine_id: str + + protocol: Optional[Literal["websocket"]] = None + + ready_at: Optional[datetime] = None + + retry_after_ms: Optional[int] = None + + status: Literal["wake_in_progress", "ready", "closed", "expired", "failed"] + + stream_url: Optional[str] = None + + terminal_id: str + + width: int diff --git a/src/dedalus_sdk/types/machines/terminal_client_event.py b/src/dedalus_sdk/types/machines/terminal_client_event.py new file mode 100644 index 0000000..52c775c --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_client_event.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Union +from typing_extensions import Annotated, TypeAlias + +from ..._utils import PropertyInfo + +from .terminal_input_event import TerminalInputEvent +from .terminal_resize_event import TerminalResizeEvent + +__all__ = ["TerminalClientEvent"] + +TerminalClientEvent: TypeAlias = Annotated[ + Union[TerminalInputEvent, TerminalResizeEvent], PropertyInfo(discriminator="type") +] diff --git a/src/dedalus_sdk/types/machines/terminal_client_event_param.py b/src/dedalus_sdk/types/machines/terminal_client_event_param.py new file mode 100644 index 0000000..65c9640 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_client_event_param.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import TypeAlias + +from .terminal_input_event_param import TerminalInputEventParam +from .terminal_resize_event_param import TerminalResizeEventParam + +__all__ = ["TerminalClientEventParam"] + + +TerminalClientEventParam: TypeAlias = Union[TerminalInputEventParam, TerminalResizeEventParam] diff --git a/src/dedalus_sdk/types/machines/terminal_closed_event.py b/src/dedalus_sdk/types/machines/terminal_closed_event.py new file mode 100644 index 0000000..4d576dd --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_closed_event.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["TerminalClosedEvent"] + + +class TerminalClosedEvent(BaseModel): + type: Literal["closed"] diff --git a/src/dedalus_sdk/types/machines/terminal_create_params.py b/src/dedalus_sdk/types/machines/terminal_create_params.py new file mode 100644 index 0000000..f547002 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_create_params.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing import Dict +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["TerminalCreateParams"] + + +class TerminalCreateParams(TypedDict, total=False): + machine_id: Required[str] + + cwd: str + + env: Dict[str, str] + + height: Required[int] + + shell: str + + width: Required[int] + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/terminal_error_event.py b/src/dedalus_sdk/types/machines/terminal_error_event.py new file mode 100644 index 0000000..f455864 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_error_event.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["TerminalErrorEvent"] + + +class TerminalErrorEvent(BaseModel): + error_code: Optional[str] = None + + error_message: Optional[str] = None + + type: Literal["error"] diff --git a/src/dedalus_sdk/types/machines/terminal_input_event.py b/src/dedalus_sdk/types/machines/terminal_input_event.py new file mode 100644 index 0000000..0cd1a3b --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_input_event.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["TerminalInputEvent"] + + +class TerminalInputEvent(BaseModel): + data: str + """Base64-encoded terminal input.""" + + type: Literal["input"] diff --git a/src/dedalus_sdk/types/machines/terminal_input_event_param.py b/src/dedalus_sdk/types/machines/terminal_input_event_param.py new file mode 100644 index 0000000..b518482 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_input_event_param.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Annotated, Literal, Required, TypedDict +from ..._types import Base64FileInput + +from ..._utils import PropertyInfo + +__all__ = ["TerminalInputEventParam"] + + +class TerminalInputEventParam(TypedDict, total=False): + data: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")]] + """Base64-encoded terminal input.""" + + type: Required[Literal["input"]] diff --git a/src/dedalus_sdk/types/machines/terminal_list.py b/src/dedalus_sdk/types/machines/terminal_list.py new file mode 100644 index 0000000..ab117b2 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_list.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import List, Optional + +from ..._models import BaseModel + +from .terminal import Terminal + +__all__ = ["TerminalList"] + + +class TerminalList(BaseModel): + items: Optional[List[Terminal]] = None + + next_cursor: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/terminal_list_params.py b/src/dedalus_sdk/types/machines/terminal_list_params.py new file mode 100644 index 0000000..d5aa311 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_list_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, Required, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["TerminalListParams"] + + +class TerminalListParams(TypedDict, total=False): + machine_id: Required[str] + + limit: int + + cursor: str + + x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/terminal_output_event.py b/src/dedalus_sdk/types/machines/terminal_output_event.py new file mode 100644 index 0000000..cc0395f --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_output_event.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["TerminalOutputEvent"] + + +class TerminalOutputEvent(BaseModel): + data: str + """Base64-encoded terminal output.""" + + type: Literal["output"] diff --git a/src/dedalus_sdk/types/machines/terminal_resize_event.py b/src/dedalus_sdk/types/machines/terminal_resize_event.py new file mode 100644 index 0000000..f6ba3a1 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_resize_event.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["TerminalResizeEvent"] + + +class TerminalResizeEvent(BaseModel): + height: int + + type: Literal["resize"] + + width: int diff --git a/src/dedalus_sdk/types/machines/terminal_resize_event_param.py b/src/dedalus_sdk/types/machines/terminal_resize_event_param.py new file mode 100644 index 0000000..7500ae5 --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_resize_event_param.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["TerminalResizeEventParam"] + + +class TerminalResizeEventParam(TypedDict, total=False): + height: Required[int] + + type: Required[Literal["resize"]] + + width: Required[int] diff --git a/src/dedalus_sdk/types/machines/terminal_server_event.py b/src/dedalus_sdk/types/machines/terminal_server_event.py new file mode 100644 index 0000000..b16a55c --- /dev/null +++ b/src/dedalus_sdk/types/machines/terminal_server_event.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Union +from typing_extensions import Annotated, TypeAlias + +from ..._utils import PropertyInfo + +from .terminal_output_event import TerminalOutputEvent +from .terminal_error_event import TerminalErrorEvent +from .terminal_closed_event import TerminalClosedEvent + +__all__ = ["TerminalServerEvent"] + +TerminalServerEvent: TypeAlias = Annotated[ + Union[TerminalOutputEvent, TerminalErrorEvent, TerminalClosedEvent], PropertyInfo(discriminator="type") +] diff --git a/src/dedalus_sdk/types/network.py b/src/dedalus_sdk/types/network.py new file mode 100644 index 0000000..c087fdf --- /dev/null +++ b/src/dedalus_sdk/types/network.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import List, Optional + +from .._models import BaseModel + +from .network_gateway import NetworkGateway + +__all__ = ["Network"] + + +class Network(BaseModel): + gateways: Optional[List[NetworkGateway]] = None + + name: str + + network_id: str diff --git a/src/dedalus_sdk/types/network_gateway.py b/src/dedalus_sdk/types/network_gateway.py new file mode 100644 index 0000000..3bda536 --- /dev/null +++ b/src/dedalus_sdk/types/network_gateway.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Optional +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["NetworkGateway"] + + +class NetworkGateway(BaseModel): + hostname: str + + kind: Literal["ssh", "port"] + + port: Optional[int] = None + + protocol: Literal["ssh", "https"] diff --git a/src/dedalus_sdk/types/org_usage.py b/src/dedalus_sdk/types/org_usage.py new file mode 100644 index 0000000..c4381d1 --- /dev/null +++ b/src/dedalus_sdk/types/org_usage.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Scalar. See README.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 guest-owned active CPU seconds for the period.""" + + billed_logical_storage_mib_seconds: int + """Closed billable logical MiB-seconds for the period.""" + + billed_memory_mib_seconds: int + """Closed requested memory MiB multiplied by running allocation 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/usage_machine_compute_params.py b/src/dedalus_sdk/types/usage_machine_compute_params.py new file mode 100644 index 0000000..f1c8a61 --- /dev/null +++ b/src/dedalus_sdk/types/usage_machine_compute_params.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["UsageMachineComputeParams"] + + +class UsageMachineComputeParams(TypedDict, total=False): + period_start: str + """Usage period start (YYYY-MM-DD). Defaults to first of current month.""" + + period_end: str + """Last UTC usage date to include (YYYY-MM-DD). Defaults to current time.""" + + machine_id: str + """Optional machine ID filter.""" + + granularity: str + """Usage breakdown granularity: hour or day. Defaults to hour.""" diff --git a/src/dedalus_sdk/types/usage_machine_storage_params.py b/src/dedalus_sdk/types/usage_machine_storage_params.py new file mode 100644 index 0000000..230ac44 --- /dev/null +++ b/src/dedalus_sdk/types/usage_machine_storage_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["UsageMachineStorageParams"] + + +class UsageMachineStorageParams(TypedDict, total=False): + period_start: str + """Usage period start (YYYY-MM-DD). Defaults to first of current month.""" + + period_end: str + """Last UTC usage date to include (YYYY-MM-DD). Defaults to current time.""" + + machine_id: str + """Optional machine ID filter.""" diff --git a/src/dedalus_sdk/types/usage_retrieve_params.py b/src/dedalus_sdk/types/usage_retrieve_params.py new file mode 100644 index 0000000..e85d9a9 --- /dev/null +++ b/src/dedalus_sdk/types/usage_retrieve_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["UsageRetrieveParams"] + + +class UsageRetrieveParams(TypedDict, total=False): + period_start: str + """Billing period start (YYYY-MM-DD). Defaults to first of current month.""" diff --git a/src/dedalus_sdk/types/websocket_connection_options.py b/src/dedalus_sdk/types/websocket_connection_options.py new file mode 100644 index 0000000..a67161d --- /dev/null +++ b/src/dedalus_sdk/types/websocket_connection_options.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING +from typing_extensions import Sequence, TypedDict + +if TYPE_CHECKING: + from websockets import Subprotocol + from websockets.extensions import ClientExtensionFactory + + +class WebSocketConnectionOptions(TypedDict, total=False): + """WebSocket connection options forwarded to `websockets.connect`.""" + + extensions: Sequence[ClientExtensionFactory] | None + subprotocols: Sequence[Subprotocol] | None + compression: str | None + max_size: int | None + max_queue: int | None | tuple[int | None, int | None] + write_limit: int | tuple[int, int | None] diff --git a/src/dedalus_sdk/types/websocket_reconnection.py b/src/dedalus_sdk/types/websocket_reconnection.py new file mode 100644 index 0000000..e4a5ce2 --- /dev/null +++ b/src/dedalus_sdk/types/websocket_reconnection.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import dataclasses +from typing_extensions import TypedDict + +from .._types import Query, Headers + + +@dataclasses.dataclass(frozen=True) +class ReconnectingEvent: + """Information about a reconnection attempt passed to `on_reconnecting`.""" + + attempt: int + max_attempts: int + delay: float + close_code: int + extra_query: Query + extra_headers: Headers + + +class ReconnectingOverrides(TypedDict, total=False): + """Optional overrides for the next WebSocket reconnection attempt.""" + + extra_query: Query + extra_headers: Headers + abort: bool + + +_RECOVERABLE_CLOSE_CODES: frozenset[int] = frozenset({1001, 1005, 1006, 1011, 1012, 1013, 1015}) + + +def is_recoverable_close(code: int) -> bool: + """Return `True` if the WebSocket close code is worth retrying.""" + return code in _RECOVERABLE_CLOSE_CODES diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index fd8019a..0000000 --- a/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/__init__.py b/tests/api_resources/__init__.py deleted file mode 100644 index fd8019a..0000000 --- a/tests/api_resources/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/machines/__init__.py b/tests/api_resources/machines/__init__.py deleted file mode 100644 index fd8019a..0000000 --- a/tests/api_resources/machines/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/machines/test_executions.py b/tests/api_resources/machines/test_executions.py deleted file mode 100644 index 87ad5c2..0000000 --- a/tests/api_resources/machines/test_executions.py +++ /dev/null @@ -1,635 +0,0 @@ -# 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.pagination import SyncCursorPage, AsyncCursorPage -from dedalus_sdk.types.machines import ( - Execution, - ExecutionEvent, - ExecutionOutput, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestExecutions: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Dedalus) -> None: - execution = client.machines.executions.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Dedalus) -> None: - execution = client.machines.executions.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - cwd="cwd", - env={"foo": "string"}, - stdin="stdin", - timeout_ms=0, - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Dedalus) -> None: - response = client.machines.executions.with_raw_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Dedalus) -> None: - with client.machines.executions.with_streaming_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_create(self, client: Dedalus) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): - client.machines.executions.with_raw_response.create( - machine_id="", - command=["string"], - ) - - @parametrize - def test_method_retrieve(self, client: Dedalus) -> None: - execution = client.machines.executions.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - def test_raw_response_retrieve(self, client: Dedalus) -> None: - response = client.machines.executions.with_raw_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - def test_streaming_response_retrieve(self, client: Dedalus) -> None: - with client.machines.executions.with_streaming_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = response.parse() - assert_matches_type(Execution, execution, 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 `machine_id` but received ''"): - client.machines.executions.with_raw_response.retrieve( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) - - @parametrize - def test_method_list(self, client: Dedalus) -> None: - execution = client.machines.executions.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - cursor="cursor", - limit=0, - ) - assert_matches_type(SyncCursorPage[Execution], execution, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Dedalus) -> None: - response = client.machines.executions.with_raw_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = response.parse() - assert_matches_type(SyncCursorPage[Execution], execution, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Dedalus) -> None: - with client.machines.executions.with_streaming_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = response.parse() - assert_matches_type(SyncCursorPage[Execution], execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_list(self, client: Dedalus) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): - client.machines.executions.with_raw_response.list( - machine_id="", - ) - - @parametrize - def test_method_delete(self, client: Dedalus) -> None: - execution = client.machines.executions.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - def test_raw_response_delete(self, client: Dedalus) -> None: - response = client.machines.executions.with_raw_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - def test_streaming_response_delete(self, client: Dedalus) -> None: - with client.machines.executions.with_streaming_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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.executions.with_raw_response.delete( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) - - @parametrize - def test_method_events(self, client: Dedalus) -> None: - execution = client.machines.executions.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(SyncCursorPage[ExecutionEvent], execution, path=["response"]) - - @parametrize - def test_method_events_with_all_params(self, client: Dedalus) -> None: - execution = client.machines.executions.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - cursor="cursor", - limit=0, - ) - assert_matches_type(SyncCursorPage[ExecutionEvent], execution, path=["response"]) - - @parametrize - def test_raw_response_events(self, client: Dedalus) -> None: - response = client.machines.executions.with_raw_response.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = response.parse() - assert_matches_type(SyncCursorPage[ExecutionEvent], execution, path=["response"]) - - @parametrize - def test_streaming_response_events(self, client: Dedalus) -> None: - with client.machines.executions.with_streaming_response.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = response.parse() - assert_matches_type(SyncCursorPage[ExecutionEvent], execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_events(self, client: Dedalus) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): - client.machines.executions.with_raw_response.events( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) - - @parametrize - def test_method_output(self, client: Dedalus) -> None: - execution = client.machines.executions.output( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(ExecutionOutput, execution, path=["response"]) - - @parametrize - def test_raw_response_output(self, client: Dedalus) -> None: - response = client.machines.executions.with_raw_response.output( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = response.parse() - assert_matches_type(ExecutionOutput, execution, path=["response"]) - - @parametrize - def test_streaming_response_output(self, client: Dedalus) -> None: - with client.machines.executions.with_streaming_response.output( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = response.parse() - assert_matches_type(ExecutionOutput, execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_output(self, client: Dedalus) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): - client.machines.executions.with_raw_response.output( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) - - -class TestAsyncExecutions: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - cwd="cwd", - env={"foo": "string"}, - stdin="stdin", - timeout_ms=0, - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.executions.with_raw_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = await response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.executions.with_streaming_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - command=["string"], - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = await response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_create(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.executions.with_raw_response.create( - machine_id="", - command=["string"], - ) - - @parametrize - async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.executions.with_raw_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = await response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.executions.with_streaming_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = await response.parse() - assert_matches_type(Execution, execution, 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 `machine_id` but received ''"): - await async_client.machines.executions.with_raw_response.retrieve( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) - - @parametrize - async def test_method_list(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - cursor="cursor", - limit=0, - ) - assert_matches_type(AsyncCursorPage[Execution], execution, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.executions.with_raw_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = await response.parse() - assert_matches_type(AsyncCursorPage[Execution], execution, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.executions.with_streaming_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = await response.parse() - assert_matches_type(AsyncCursorPage[Execution], execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_list(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.executions.with_raw_response.list( - machine_id="", - ) - - @parametrize - async def test_method_delete(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.executions.with_raw_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = await response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.executions.with_streaming_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = await response.parse() - assert_matches_type(Execution, execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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.executions.with_raw_response.delete( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) - - @parametrize - async def test_method_events(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(AsyncCursorPage[ExecutionEvent], execution, path=["response"]) - - @parametrize - async def test_method_events_with_all_params(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - cursor="cursor", - limit=0, - ) - assert_matches_type(AsyncCursorPage[ExecutionEvent], execution, path=["response"]) - - @parametrize - async def test_raw_response_events(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.executions.with_raw_response.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = await response.parse() - assert_matches_type(AsyncCursorPage[ExecutionEvent], execution, path=["response"]) - - @parametrize - async def test_streaming_response_events(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.executions.with_streaming_response.events( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = await response.parse() - assert_matches_type(AsyncCursorPage[ExecutionEvent], execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_events(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.executions.with_raw_response.events( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) - - @parametrize - async def test_method_output(self, async_client: AsyncDedalus) -> None: - execution = await async_client.machines.executions.output( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - assert_matches_type(ExecutionOutput, execution, path=["response"]) - - @parametrize - async def test_raw_response_output(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.executions.with_raw_response.output( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - execution = await response.parse() - assert_matches_type(ExecutionOutput, execution, path=["response"]) - - @parametrize - async def test_streaming_response_output(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.executions.with_streaming_response.output( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="execution_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - execution = await response.parse() - assert_matches_type(ExecutionOutput, execution, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_output(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.executions.with_raw_response.output( - machine_id="", - execution_id="execution_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - execution_id="", - ) diff --git a/tests/api_resources/machines/test_ssh.py b/tests/api_resources/machines/test_ssh.py deleted file mode 100644 index 65ba42c..0000000 --- a/tests/api_resources/machines/test_ssh.py +++ /dev/null @@ -1,395 +0,0 @@ -# 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.pagination import SyncCursorPage, AsyncCursorPage -from dedalus_sdk.types.machines import SSHSession - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestSSH: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Dedalus) -> None: - ssh = client.machines.ssh.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - public_key="public_key", - ) - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Dedalus) -> None: - response = client.machines.ssh.with_raw_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - public_key="public_key", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Dedalus) -> None: - with client.machines.ssh.with_streaming_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - public_key="public_key", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_create(self, client: Dedalus) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): - client.machines.ssh.with_raw_response.create( - machine_id="", - public_key="public_key", - ) - - @parametrize - def test_method_retrieve(self, client: Dedalus) -> None: - ssh = client.machines.ssh.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - def test_raw_response_retrieve(self, client: Dedalus) -> None: - response = client.machines.ssh.with_raw_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - def test_streaming_response_retrieve(self, client: Dedalus) -> None: - with client.machines.ssh.with_streaming_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = response.parse() - assert_matches_type(SSHSession, ssh, 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 `machine_id` but received ''"): - client.machines.ssh.with_raw_response.retrieve( - machine_id="", - session_id="session_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="", - ) - - @parametrize - def test_method_list(self, client: Dedalus) -> None: - ssh = client.machines.ssh.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - cursor="cursor", - limit=0, - ) - assert_matches_type(SyncCursorPage[SSHSession], ssh, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Dedalus) -> None: - response = client.machines.ssh.with_raw_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = response.parse() - assert_matches_type(SyncCursorPage[SSHSession], ssh, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Dedalus) -> None: - with client.machines.ssh.with_streaming_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = response.parse() - assert_matches_type(SyncCursorPage[SSHSession], ssh, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_path_params_list(self, client: Dedalus) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `machine_id` but received ''"): - client.machines.ssh.with_raw_response.list( - machine_id="", - ) - - @parametrize - def test_method_delete(self, client: Dedalus) -> None: - ssh = client.machines.ssh.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - def test_raw_response_delete(self, client: Dedalus) -> None: - response = client.machines.ssh.with_raw_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - def test_streaming_response_delete(self, client: Dedalus) -> None: - with client.machines.ssh.with_streaming_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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.ssh.with_raw_response.delete( - machine_id="", - session_id="session_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="", - ) - - -class TestAsyncSSH: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncDedalus) -> None: - ssh = await async_client.machines.ssh.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - public_key="public_key", - ) - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - async def test_raw_response_create(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.ssh.with_raw_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - public_key="public_key", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = await response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.ssh.with_streaming_response.create( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - public_key="public_key", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = await response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_create(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.ssh.with_raw_response.create( - machine_id="", - public_key="public_key", - ) - - @parametrize - async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: - ssh = await async_client.machines.ssh.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.ssh.with_raw_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = await response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.ssh.with_streaming_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = await response.parse() - assert_matches_type(SSHSession, ssh, 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 `machine_id` but received ''"): - await async_client.machines.ssh.with_raw_response.retrieve( - machine_id="", - session_id="session_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="", - ) - - @parametrize - async def test_method_list(self, async_client: AsyncDedalus) -> None: - ssh = await async_client.machines.ssh.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - cursor="cursor", - limit=0, - ) - assert_matches_type(AsyncCursorPage[SSHSession], ssh, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.ssh.with_raw_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = await response.parse() - assert_matches_type(AsyncCursorPage[SSHSession], ssh, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.ssh.with_streaming_response.list( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = await response.parse() - assert_matches_type(AsyncCursorPage[SSHSession], ssh, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_path_params_list(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.ssh.with_raw_response.list( - machine_id="", - ) - - @parametrize - async def test_method_delete(self, async_client: AsyncDedalus) -> None: - ssh = await async_client.machines.ssh.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - async def test_raw_response_delete(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.ssh.with_raw_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - ssh = await response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.ssh.with_streaming_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="session_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - ssh = await response.parse() - assert_matches_type(SSHSession, ssh, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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.ssh.with_raw_response.delete( - machine_id="", - session_id="session_id", - ) - - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - session_id="", - ) diff --git a/tests/api_resources/test_machines.py b/tests/api_resources/test_machines.py deleted file mode 100644 index dbdfeef..0000000 --- a/tests/api_resources/test_machines.py +++ /dev/null @@ -1,567 +0,0 @@ -# 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 import ( - Machine, - MachineListItem, - MachineRetrieveResponse, -) -from dedalus_sdk.pagination import SyncCursorPage, AsyncCursorPage - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestMachines: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create(self, client: Dedalus) -> None: - machine = client.machines.create() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_method_create_with_all_params(self, client: Dedalus) -> None: - machine = client.machines.create( - autosleep="autosleep", - memory_mib=1, - storage_gib=1, - vcpu=1, - ) - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_raw_response_create(self, client: Dedalus) -> None: - response = client.machines.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_streaming_response_create(self, client: Dedalus) -> None: - with client.machines.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_retrieve(self, client: Dedalus) -> None: - machine = client.machines.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - assert_matches_type(MachineRetrieveResponse, machine, path=["response"]) - - @parametrize - def test_raw_response_retrieve(self, client: Dedalus) -> None: - response = client.machines.with_raw_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = response.parse() - assert_matches_type(MachineRetrieveResponse, machine, path=["response"]) - - @parametrize - def test_streaming_response_retrieve(self, client: Dedalus) -> None: - with client.machines.with_streaming_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = response.parse() - assert_matches_type(MachineRetrieveResponse, machine, 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 `machine_id` but received ''"): - client.machines.with_raw_response.retrieve( - machine_id="", - ) - - @parametrize - def test_method_update(self, client: Dedalus) -> None: - machine = client.machines.update( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - autosleep="autosleep", - memory_mib=0, - storage_gib=0, - vcpu=0, - ) - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_raw_response_update(self, client: Dedalus) -> None: - response = client.machines.with_raw_response.update( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_streaming_response_update(self, client: Dedalus) -> None: - with client.machines.with_streaming_response.update( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) - - @parametrize - def test_method_list(self, client: Dedalus) -> None: - machine = client.machines.list() - assert_matches_type(SyncCursorPage[MachineListItem], machine, path=["response"]) - - @parametrize - def test_method_list_with_all_params(self, client: Dedalus) -> None: - machine = client.machines.list( - cursor="cursor", - limit=0, - ) - assert_matches_type(SyncCursorPage[MachineListItem], machine, path=["response"]) - - @parametrize - def test_raw_response_list(self, client: Dedalus) -> None: - response = client.machines.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = response.parse() - assert_matches_type(SyncCursorPage[MachineListItem], machine, path=["response"]) - - @parametrize - def test_streaming_response_list(self, client: Dedalus) -> None: - with client.machines.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = response.parse() - assert_matches_type(SyncCursorPage[MachineListItem], machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - def test_method_delete(self, client: Dedalus) -> None: - machine = client.machines.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_streaming_response_delete(self, client: Dedalus) -> None: - with client.machines.with_streaming_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) - - @parametrize - def test_method_sleep(self, client: Dedalus) -> None: - machine = client.machines.sleep( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_streaming_response_sleep(self, client: Dedalus) -> None: - with client.machines.with_streaming_response.sleep( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) - - @parametrize - def test_method_wake(self, client: Dedalus) -> None: - machine = client.machines.wake( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - def test_streaming_response_wake(self, client: Dedalus) -> None: - with client.machines.with_streaming_response.wake( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) - - -class TestAsyncMachines: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_create(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.create() - 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( - autosleep="autosleep", - memory_mib=1, - storage_gib=1, - vcpu=1, - ) - 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() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - async def test_streaming_response_create(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_retrieve(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - assert_matches_type(MachineRetrieveResponse, 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = await response.parse() - assert_matches_type(MachineRetrieveResponse, machine, path=["response"]) - - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.with_streaming_response.retrieve( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = await response.parse() - assert_matches_type(MachineRetrieveResponse, machine, 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 `machine_id` but received ''"): - await async_client.machines.with_raw_response.retrieve( - machine_id="", - ) - - @parametrize - async def test_method_update(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.update( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - autosleep="autosleep", - memory_mib=0, - storage_gib=0, - vcpu=0, - ) - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - async def test_raw_response_update(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.with_raw_response.update( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - async def test_streaming_response_update(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.with_streaming_response.update( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) - - @parametrize - async def test_method_list(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.list() - assert_matches_type(AsyncCursorPage[MachineListItem], machine, path=["response"]) - - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.list( - cursor="cursor", - limit=0, - ) - assert_matches_type(AsyncCursorPage[MachineListItem], machine, path=["response"]) - - @parametrize - async def test_raw_response_list(self, async_client: AsyncDedalus) -> None: - response = await async_client.machines.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = await response.parse() - assert_matches_type(AsyncCursorPage[MachineListItem], machine, path=["response"]) - - @parametrize - async def test_streaming_response_list(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = await response.parse() - assert_matches_type(AsyncCursorPage[MachineListItem], machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - async def test_method_delete(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.with_streaming_response.delete( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) - - @parametrize - async def test_method_sleep(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.sleep( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - async def test_streaming_response_sleep(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.with_streaming_response.sleep( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) - - @parametrize - async def test_method_wake(self, async_client: AsyncDedalus) -> None: - machine = await async_client.machines.wake( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - 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="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - @parametrize - async def test_streaming_response_wake(self, async_client: AsyncDedalus) -> None: - async with async_client.machines.with_streaming_response.wake( - machine_id="dm-ecc2efdd-ddfa-31a9-c6f1-b833d337aa7c", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - machine = await response.parse() - assert_matches_type(Machine, machine, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @parametrize - 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="", - ) diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index db34904..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,84 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -import logging -from typing import TYPE_CHECKING, Iterator, AsyncIterator - -import httpx -import pytest -from pytest_asyncio import is_async_test - -from dedalus_sdk import Dedalus, AsyncDedalus, DefaultAioHttpClient -from dedalus_sdk._utils import is_dict - -if TYPE_CHECKING: - from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] - -pytest.register_assert_rewrite("tests.utils") - -logging.getLogger("dedalus_sdk").setLevel(logging.DEBUG) - - -# automatically add `pytest.mark.asyncio()` to all of our async tests -# so we don't have to add that boilerplate everywhere -def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: - pytest_asyncio_tests = (item for item in items if is_async_test(item)) - session_scope_marker = pytest.mark.asyncio(loop_scope="session") - for async_test in pytest_asyncio_tests: - async_test.add_marker(session_scope_marker, append=False) - - # We skip tests that use both the aiohttp client and respx_mock as respx_mock - # doesn't support custom transports. - for item in items: - if "async_client" not in item.fixturenames or "respx_mock" not in item.fixturenames: - continue - - if not hasattr(item, "callspec"): - continue - - async_client_param = item.callspec.params.get("async_client") - if is_dict(async_client_param) and async_client_param.get("http_client") == "aiohttp": - item.add_marker(pytest.mark.skip(reason="aiohttp client is not compatible with respx_mock")) - - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - -api_key = "My API Key" - - -@pytest.fixture(scope="session") -def client(request: FixtureRequest) -> Iterator[Dedalus]: - strict = getattr(request, "param", True) - if not isinstance(strict, bool): - raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") - - with Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: - yield client - - -@pytest.fixture(scope="session") -async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncDedalus]: - param = getattr(request, "param", True) - - # defaults - strict = True - http_client: None | httpx.AsyncClient = None - - if isinstance(param, bool): - strict = param - elif is_dict(param): - strict = param.get("strict", True) - assert isinstance(strict, bool) - - http_client_type = param.get("http_client", "httpx") - if http_client_type == "aiohttp": - http_client = DefaultAioHttpClient() - else: - raise TypeError(f"Unexpected fixture parameter type {type(param)}, expected bool or dict") - - async with AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=strict, http_client=http_client - ) as client: - yield client diff --git a/tests/sample_file.txt b/tests/sample_file.txt deleted file mode 100644 index af5626b..0000000 --- a/tests/sample_file.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, world! diff --git a/tests/smoke-test.py b/tests/smoke-test.py new file mode 100644 index 0000000..459e956 --- /dev/null +++ b/tests/smoke-test.py @@ -0,0 +1,1163 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +# Smoke test: calls every generated operation once to confirm the SDK can reach each endpoint. +# Run it from this repo with `python tests/smoke-test.py`. The generator also runs this file +# against a mock server and reads the JSON report produced via SCALAR_SMOKE_REPORT. +from __future__ import annotations + +import json +import os +import sys +import time +import traceback +from concurrent.futures import ThreadPoolExecutor +from pathlib import Path +from typing import Any, Callable, TypedDict + +from dedalus_sdk import Dedalus + +# The shared smoke-test runner injects base URL and credentials through the same +# environment variables the generated client reads in normal use. +client = Dedalus(max_retries=2, timeout=10) + + +class SmokeResult(TypedDict, total=False): + operation: str + method: str + path: str + label: str + status: str + durationMs: int + error: str + + +class _SmokeCaseBase(TypedDict): + operation: str + method: str + path: str + run: Callable[[], Any] + + +# `label` says which of an operation's two calls this is — "required params" or "all params". +# It sits in a total=False extension because it is absent when the operation contributed a +# single case, while the fields above are always present. +class SmokeCase(_SmokeCaseBase, total=False): + label: str + + +def _smoke_case_0() -> None: + page = client.machines.list() + + +def _smoke_case_1() -> None: + page = client.machines.list( + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_2() -> None: + machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + idempotency_key="", + ) + + +def _smoke_case_3() -> None: + machine = client.machines.create( + autosleep="300s", + memory_mib=4096, + storage_gib=10, + vcpu=1, + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_4() -> None: + machine = client.machines.retrieve( + machine_id="machineID", + ) + + +def _smoke_case_5() -> None: + machine = client.machines.retrieve( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_6() -> None: + machine = client.machines.update( + machine_id="machineID", + idempotency_key="", + ) + + +def _smoke_case_7() -> None: + machine = client.machines.update( + machine_id="machineID", + autosleep="", + memory_mib=0, + storage_gib=0, + vcpu=0, + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_8() -> None: + machine = client.machines.delete( + machine_id="machineID", + idempotency_key="", + ) + + +def _smoke_case_9() -> None: + machine = client.machines.delete( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_10() -> None: + stream = client.machines.watch( + machine_id="machineID", + ) + + for machine in stream: + print(machine) + + +def _smoke_case_11() -> None: + stream = client.machines.watch( + machine_id="machineID", + x_dedalus_org_id="7c9e6679-7425-40de-944b-e07fc1f90ae7", + last_event_id="last_event_id", + ) + + for machine in stream: + print(machine) + + +def _smoke_case_12() -> None: + machine = client.machines.sleep( + machine_id="machineID", + idempotency_key="", + ) + + +def _smoke_case_13() -> None: + machine = client.machines.sleep( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_14() -> None: + machine = client.machines.wake( + machine_id="machineID", + idempotency_key="", + ) + + +def _smoke_case_15() -> None: + machine = client.machines.wake( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_16() -> None: + network = client.machines.network.retrieve( + machine_id="machineID", + ) + + +def _smoke_case_17() -> None: + network = client.machines.network.retrieve( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_18() -> None: + page = client.machines.artifacts.list( + machine_id="machineID", + ) + + +def _smoke_case_19() -> None: + page = client.machines.artifacts.list( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_20() -> None: + artifact = client.machines.artifacts.retrieve( + machine_id="machineID", + artifact_id="artifactID", + ) + + +def _smoke_case_21() -> None: + artifact = client.machines.artifacts.retrieve( + machine_id="machineID", + artifact_id="artifactID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_22() -> None: + artifact = client.machines.artifacts.delete( + machine_id="machineID", + artifact_id="artifactID", + idempotency_key="", + ) + + +def _smoke_case_23() -> None: + artifact = client.machines.artifacts.delete( + machine_id="machineID", + artifact_id="artifactID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_24() -> None: + page = client.machines.ports.list( + machine_id="machineID", + ) + + +def _smoke_case_25() -> None: + page = client.machines.ports.list( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_26() -> None: + port = client.machines.ports.create( + machine_id="machineID", + port=0, + idempotency_key="", + ) + + +def _smoke_case_27() -> None: + port = client.machines.ports.create( + machine_id="machineID", + port=0, + protocol="http", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_28() -> None: + port = client.machines.ports.retrieve( + machine_id="machineID", + port_id="portID", + ) + + +def _smoke_case_29() -> None: + port = client.machines.ports.retrieve( + machine_id="machineID", + port_id="portID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_30() -> None: + port = client.machines.ports.delete( + machine_id="machineID", + port_id="portID", + idempotency_key="", + ) + + +def _smoke_case_31() -> None: + port = client.machines.ports.delete( + machine_id="machineID", + port_id="portID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_32() -> None: + page = client.machines.ssh.list( + machine_id="machineID", + ) + + +def _smoke_case_33() -> None: + page = client.machines.ssh.list( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_34() -> None: + ssh = client.machines.ssh.create( + machine_id="machineID", + public_key="", + idempotency_key="", + ) + + +def _smoke_case_35() -> None: + ssh = client.machines.ssh.create( + machine_id="machineID", + public_key="", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_36() -> None: + ssh = client.machines.ssh.retrieve( + machine_id="machineID", + session_id="sessionID", + ) + + +def _smoke_case_37() -> None: + ssh = client.machines.ssh.retrieve( + machine_id="machineID", + session_id="sessionID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_38() -> None: + ssh = client.machines.ssh.delete( + machine_id="machineID", + session_id="sessionID", + idempotency_key="", + ) + + +def _smoke_case_39() -> None: + ssh = client.machines.ssh.delete( + machine_id="machineID", + session_id="sessionID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_40() -> None: + page = client.machines.executions.list( + machine_id="machineID", + ) + + +def _smoke_case_41() -> None: + page = client.machines.executions.list( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_42() -> None: + execution = client.machines.executions.create( + machine_id="machineID", + command=[""], + idempotency_key="", + ) + + +def _smoke_case_43() -> None: + execution = client.machines.executions.create( + machine_id="machineID", + command=[""], + cwd="", + env={}, + stdin="", + timeout_ms=0, + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_44() -> None: + execution = client.machines.executions.retrieve( + machine_id="machineID", + execution_id="executionID", + ) + + +def _smoke_case_45() -> None: + execution = client.machines.executions.retrieve( + machine_id="machineID", + execution_id="executionID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_46() -> None: + execution = client.machines.executions.delete( + machine_id="machineID", + execution_id="executionID", + idempotency_key="", + ) + + +def _smoke_case_47() -> None: + execution = client.machines.executions.delete( + machine_id="machineID", + execution_id="executionID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_48() -> None: + execution = client.machines.executions.output( + machine_id="machineID", + execution_id="executionID", + ) + + +def _smoke_case_49() -> None: + execution = client.machines.executions.output( + machine_id="machineID", + execution_id="executionID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_50() -> None: + page = client.machines.executions.events( + machine_id="machineID", + execution_id="executionID", + ) + + +def _smoke_case_51() -> None: + page = client.machines.executions.events( + machine_id="machineID", + execution_id="executionID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_52() -> None: + page = client.machines.terminals.list( + machine_id="machineID", + ) + + +def _smoke_case_53() -> None: + page = client.machines.terminals.list( + machine_id="machineID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_54() -> None: + terminal = client.machines.terminals.create( + machine_id="machineID", + height=0, + width=0, + idempotency_key="", + ) + + +def _smoke_case_55() -> None: + terminal = client.machines.terminals.create( + machine_id="machineID", + cwd="", + env={}, + height=0, + shell="", + width=0, + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_56() -> None: + terminal = client.machines.terminals.retrieve( + machine_id="machineID", + terminal_id="terminalID", + ) + + +def _smoke_case_57() -> None: + terminal = client.machines.terminals.retrieve( + machine_id="machineID", + terminal_id="terminalID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_58() -> None: + terminal = client.machines.terminals.delete( + machine_id="machineID", + terminal_id="terminalID", + idempotency_key="", + ) + + +def _smoke_case_59() -> None: + terminal = client.machines.terminals.delete( + machine_id="machineID", + terminal_id="terminalID", + x_dedalus_org_id="x_dedalus_org_id", + idempotency_key="", + ) + + +def _smoke_case_60() -> None: + def _probe() -> None: + with client.machines.terminals.connect( + machine_id="machineID", + terminal_id="terminalID", + ) as socket: + try: + socket.recv() + finally: + socket.close(code=1000, reason="smoke-test") + + _probe() + + +def _smoke_case_61() -> None: + network = client.networks.retrieve( + network_id="networkID", + ) + + +def _smoke_case_62() -> None: + network = client.networks.retrieve( + network_id="networkID", + x_dedalus_org_id="x_dedalus_org_id", + ) + + +def _smoke_case_63() -> None: + usage = client.usage.retrieve() + + +def _smoke_case_64() -> None: + usage = client.usage.retrieve( + period_start="period_start", + ) + + +def _smoke_case_65() -> None: + usage = client.usage.machine_compute() + + +def _smoke_case_66() -> None: + usage = client.usage.machine_compute( + period_start="period_start", + period_end="period_end", + machine_id="machine_id", + granularity="granularity", + ) + + +def _smoke_case_67() -> None: + usage = client.usage.machine_storage() + + +def _smoke_case_68() -> None: + usage = client.usage.machine_storage( + period_start="period_start", + period_end="period_end", + machine_id="machine_id", + ) + + +cases: list[SmokeCase] = [ + { + "operation": "list", + "method": "GET", + "path": "/v1/machines", + "label": "required params", + "run": _smoke_case_0, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines", + "label": "all params", + "run": _smoke_case_1, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines", + "label": "required params", + "run": _smoke_case_2, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines", + "label": "all params", + "run": _smoke_case_3, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}", + "label": "required params", + "run": _smoke_case_4, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}", + "label": "all params", + "run": _smoke_case_5, + }, + { + "operation": "update", + "method": "PATCH", + "path": "/v1/machines/{machine_id}", + "label": "required params", + "run": _smoke_case_6, + }, + { + "operation": "update", + "method": "PATCH", + "path": "/v1/machines/{machine_id}", + "label": "all params", + "run": _smoke_case_7, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}", + "label": "required params", + "run": _smoke_case_8, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}", + "label": "all params", + "run": _smoke_case_9, + }, + { + "operation": "watch", + "method": "GET", + "path": "/v1/machines/{machine_id}/status/stream", + "label": "required params", + "run": _smoke_case_10, + }, + { + "operation": "watch", + "method": "GET", + "path": "/v1/machines/{machine_id}/status/stream", + "label": "all params", + "run": _smoke_case_11, + }, + { + "operation": "sleep", + "method": "POST", + "path": "/v1/machines/{machine_id}/sleep", + "label": "required params", + "run": _smoke_case_12, + }, + { + "operation": "sleep", + "method": "POST", + "path": "/v1/machines/{machine_id}/sleep", + "label": "all params", + "run": _smoke_case_13, + }, + { + "operation": "wake", + "method": "POST", + "path": "/v1/machines/{machine_id}/wake", + "label": "required params", + "run": _smoke_case_14, + }, + { + "operation": "wake", + "method": "POST", + "path": "/v1/machines/{machine_id}/wake", + "label": "all params", + "run": _smoke_case_15, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/network", + "label": "required params", + "run": _smoke_case_16, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/network", + "label": "all params", + "run": _smoke_case_17, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/artifacts", + "label": "required params", + "run": _smoke_case_18, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/artifacts", + "label": "all params", + "run": _smoke_case_19, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", + "label": "required params", + "run": _smoke_case_20, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", + "label": "all params", + "run": _smoke_case_21, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", + "label": "required params", + "run": _smoke_case_22, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", + "label": "all params", + "run": _smoke_case_23, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/ports", + "label": "required params", + "run": _smoke_case_24, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/ports", + "label": "all params", + "run": _smoke_case_25, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/ports", + "label": "required params", + "run": _smoke_case_26, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/ports", + "label": "all params", + "run": _smoke_case_27, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/ports/{port_id}", + "label": "required params", + "run": _smoke_case_28, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/ports/{port_id}", + "label": "all params", + "run": _smoke_case_29, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ports/{port_id}", + "label": "required params", + "run": _smoke_case_30, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ports/{port_id}", + "label": "all params", + "run": _smoke_case_31, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh", + "label": "required params", + "run": _smoke_case_32, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh", + "label": "all params", + "run": _smoke_case_33, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/ssh", + "label": "required params", + "run": _smoke_case_34, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/ssh", + "label": "all params", + "run": _smoke_case_35, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "label": "required params", + "run": _smoke_case_36, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "label": "all params", + "run": _smoke_case_37, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "label": "required params", + "run": _smoke_case_38, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "label": "all params", + "run": _smoke_case_39, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions", + "label": "required params", + "run": _smoke_case_40, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions", + "label": "all params", + "run": _smoke_case_41, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/executions", + "label": "required params", + "run": _smoke_case_42, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/executions", + "label": "all params", + "run": _smoke_case_43, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "label": "required params", + "run": _smoke_case_44, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "label": "all params", + "run": _smoke_case_45, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "label": "required params", + "run": _smoke_case_46, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "label": "all params", + "run": _smoke_case_47, + }, + { + "operation": "output", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", + "label": "required params", + "run": _smoke_case_48, + }, + { + "operation": "output", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", + "label": "all params", + "run": _smoke_case_49, + }, + { + "operation": "events", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", + "label": "required params", + "run": _smoke_case_50, + }, + { + "operation": "events", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", + "label": "all params", + "run": _smoke_case_51, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals", + "label": "required params", + "run": _smoke_case_52, + }, + { + "operation": "list", + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals", + "label": "all params", + "run": _smoke_case_53, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/terminals", + "label": "required params", + "run": _smoke_case_54, + }, + { + "operation": "create", + "method": "POST", + "path": "/v1/machines/{machine_id}/terminals", + "label": "all params", + "run": _smoke_case_55, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "label": "required params", + "run": _smoke_case_56, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "label": "all params", + "run": _smoke_case_57, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "label": "required params", + "run": _smoke_case_58, + }, + { + "operation": "delete", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "label": "all params", + "run": _smoke_case_59, + }, + { + "operation": "connect", + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", + "run": _smoke_case_60, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/networks/{network_id}", + "label": "required params", + "run": _smoke_case_61, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/networks/{network_id}", + "label": "all params", + "run": _smoke_case_62, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/usage", + "label": "required params", + "run": _smoke_case_63, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/usage", + "label": "all params", + "run": _smoke_case_64, + }, + { + "operation": "machineCompute", + "method": "GET", + "path": "/v1/usage/machines/compute", + "label": "required params", + "run": _smoke_case_65, + }, + { + "operation": "machineCompute", + "method": "GET", + "path": "/v1/usage/machines/compute", + "label": "all params", + "run": _smoke_case_66, + }, + { + "operation": "machineStorage", + "method": "GET", + "path": "/v1/usage/machines/storage", + "label": "required params", + "run": _smoke_case_67, + }, + { + "operation": "machineStorage", + "method": "GET", + "path": "/v1/usage/machines/storage", + "label": "all params", + "run": _smoke_case_68, + }, +] + +DEFAULT_SMOKE_CONCURRENCY = 32 + + +def _selected_cases() -> list[SmokeCase]: + filter_value = os.environ.get("SCALAR_SMOKE_FILTER") + needles = [needle.strip() for needle in filter_value.split(",") if needle.strip()] if filter_value else [] + if not needles: + return cases + return [case for case in cases if any(needle in case["operation"] or needle in case["path"] for needle in needles)] + + +def _smoke_concurrency(case_count: int) -> int: + override = os.environ.get("SCALAR_SMOKE_CONCURRENCY") + if override: + try: + parsed = int(override) + if parsed > 0: + return min(parsed, case_count) + except ValueError: + pass + return min(DEFAULT_SMOKE_CONCURRENCY, case_count) + + +def _case_identity(case: SmokeCase) -> SmokeResult: + # `label` is carried through only when the operation contributed both of its calls, so a + # single-case operation reports exactly as it did before there were two. + identity: SmokeResult = { + "operation": case["operation"], + "method": case["method"], + "path": case["path"], + } + label = case.get("label") + if label: + identity["label"] = label + return identity + + +def _run_case(case: SmokeCase) -> SmokeResult: + started_at = time.monotonic() + identity = _case_identity(case) + try: + case["run"]() + return { + **identity, + "status": "passed", + "durationMs": int((time.monotonic() - started_at) * 1000), + } + except Exception: + return { + **identity, + "status": "failed", + "durationMs": int((time.monotonic() - started_at) * 1000), + "error": traceback.format_exc(), + } + + +def main() -> None: + selected = _selected_cases() + if selected: + # Keep enough parallelism to catch generated SDK concurrency bugs without overwhelming + # CI runners or the in-process mock server for large SDKs. + with ThreadPoolExecutor(max_workers=_smoke_concurrency(len(selected))) as executor: + results = list(executor.map(_run_case, selected)) + else: + results = [] + failed = [result for result in results if result["status"] == "failed"] + + report_path = os.environ.get("SCALAR_SMOKE_REPORT") + if report_path: + Path(report_path).write_text( + json.dumps({"total": len(results), "failed": len(failed), "results": results}), encoding="utf-8" + ) + else: + for result in results: + suffix = f" [{result['label']}]" if result.get("label") else "" + if result["status"] == "passed": + print( + f"PASS {result['operation']}{suffix} ({result['method']} {result['path']}) {result['durationMs']}ms" + ) + else: + print( + f"FAIL {result['operation']}{suffix} ({result['method']} {result['path']})\n{result.get('error', '')}", + file=sys.stderr, + ) + if not results: + print("No code samples ran (empty SDK or a SCALAR_SMOKE_FILTER that matched nothing).", file=sys.stderr) + else: + print(f"\n{len(results) - len(failed)}/{len(results)} samples passed") + + if failed or not results: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/tests/test_client.py b/tests/test_client.py deleted file mode 100644 index c230dbd..0000000 --- a/tests/test_client.py +++ /dev/null @@ -1,2040 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import gc -import os -import sys -import json -import asyncio -import inspect -import dataclasses -import tracemalloc -from typing import Any, Union, TypeVar, Callable, Iterable, Iterator, Optional, Coroutine, cast -from unittest import mock -from typing_extensions import Literal, AsyncIterator, override - -import httpx -import pytest -from respx import MockRouter -from pydantic import ValidationError - -from dedalus_sdk import Dedalus, AsyncDedalus, APIResponseValidationError -from dedalus_sdk._types import Omit -from dedalus_sdk._utils import asyncify -from dedalus_sdk._models import BaseModel, FinalRequestOptions -from dedalus_sdk._exceptions import APIStatusError, APITimeoutError, APIResponseValidationError -from dedalus_sdk._base_client import ( - DEFAULT_TIMEOUT, - HTTPX_DEFAULT_TIMEOUT, - BaseClient, - OtherPlatform, - DefaultHttpxClient, - DefaultAsyncHttpxClient, - get_platform, - make_request_options, -) - -from .utils import update_env - -T = TypeVar("T") -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -api_key = "My API Key" - - -def _get_params(client: BaseClient[Any, Any]) -> dict[str, str]: - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - url = httpx.URL(request.url) - return dict(url.params) - - -def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: - return 0.1 - - -def mirror_request_content(request: httpx.Request) -> httpx.Response: - return httpx.Response(200, content=request.content) - - -# note: we can't use the httpx.MockTransport class as it consumes the request -# body itself, which means we can't test that the body is read lazily -class MockTransport(httpx.BaseTransport, httpx.AsyncBaseTransport): - def __init__( - self, - handler: Callable[[httpx.Request], httpx.Response] - | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], - ) -> None: - self.handler = handler - - @override - def handle_request( - self, - request: httpx.Request, - ) -> httpx.Response: - assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" - assert inspect.isfunction(self.handler), "handler must be a function" - return self.handler(request) - - @override - async def handle_async_request( - self, - request: httpx.Request, - ) -> httpx.Response: - assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" - return await self.handler(request) - - -@dataclasses.dataclass -class Counter: - value: int = 0 - - -def _make_sync_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> Iterator[T]: - for item in iterable: - if counter: - counter.value += 1 - yield item - - -async def _make_async_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> AsyncIterator[T]: - for item in iterable: - if counter: - counter.value += 1 - yield item - - -def _get_open_connections(client: Dedalus | AsyncDedalus) -> int: - transport = client._client._transport - assert isinstance(transport, httpx.HTTPTransport) or isinstance(transport, httpx.AsyncHTTPTransport) - - pool = transport._pool - return len(pool._requests) - - -class TestDedalus: - @pytest.mark.respx(base_url=base_url) - def test_raw_response(self, respx_mock: MockRouter, client: Dedalus) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - response = client.post("/foo", cast_to=httpx.Response) - assert response.status_code == 200 - assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} - - @pytest.mark.respx(base_url=base_url) - def test_raw_response_for_binary(self, respx_mock: MockRouter, client: Dedalus) -> None: - respx_mock.post("/foo").mock( - return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') - ) - - response = client.post("/foo", cast_to=httpx.Response) - assert response.status_code == 200 - assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} - - def test_copy(self, client: Dedalus) -> None: - copied = client.copy() - assert id(copied) != id(client) - - copied = client.copy(api_key="another My API Key") - assert copied.api_key == "another My API Key" - assert client.api_key == "My API Key" - - def test_copy_default_options(self, client: Dedalus) -> None: - # options that have a default are overridden correctly - copied = client.copy(max_retries=7) - assert copied.max_retries == 7 - assert client.max_retries == 2 - - copied2 = copied.copy(max_retries=6) - assert copied2.max_retries == 6 - assert copied.max_retries == 7 - - # timeout - assert isinstance(client.timeout, httpx.Timeout) - copied = client.copy(timeout=None) - assert copied.timeout is None - assert isinstance(client.timeout, httpx.Timeout) - - def test_copy_default_headers(self) -> None: - client = Dedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - assert client.default_headers["X-Foo"] == "bar" - - # does not override the already given value when not specified - copied = client.copy() - assert copied.default_headers["X-Foo"] == "bar" - - # merges already given headers - copied = client.copy(default_headers={"X-Bar": "stainless"}) - assert copied.default_headers["X-Foo"] == "bar" - assert copied.default_headers["X-Bar"] == "stainless" - - # uses new values for any already given headers - copied = client.copy(default_headers={"X-Foo": "stainless"}) - assert copied.default_headers["X-Foo"] == "stainless" - - # set_default_headers - - # completely overrides already set values - copied = client.copy(set_default_headers={}) - assert copied.default_headers.get("X-Foo") is None - - copied = client.copy(set_default_headers={"X-Bar": "Robert"}) - assert copied.default_headers["X-Bar"] == "Robert" - - with pytest.raises( - ValueError, - match="`default_headers` and `set_default_headers` arguments are mutually exclusive", - ): - client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) - client.close() - - def test_copy_default_query(self) -> None: - client = Dedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} - ) - assert _get_params(client)["foo"] == "bar" - - # does not override the already given value when not specified - copied = client.copy() - assert _get_params(copied)["foo"] == "bar" - - # merges already given params - copied = client.copy(default_query={"bar": "stainless"}) - params = _get_params(copied) - assert params["foo"] == "bar" - assert params["bar"] == "stainless" - - # uses new values for any already given headers - copied = client.copy(default_query={"foo": "stainless"}) - assert _get_params(copied)["foo"] == "stainless" - - # set_default_query - - # completely overrides already set values - copied = client.copy(set_default_query={}) - assert _get_params(copied) == {} - - copied = client.copy(set_default_query={"bar": "Robert"}) - assert _get_params(copied)["bar"] == "Robert" - - with pytest.raises( - ValueError, - # TODO: update - match="`default_query` and `set_default_query` arguments are mutually exclusive", - ): - client.copy(set_default_query={}, default_query={"foo": "Bar"}) - - client.close() - - def test_copy_signature(self, client: Dedalus) -> None: - # ensure the same parameters that can be passed to the client are defined in the `.copy()` method - init_signature = inspect.signature( - # mypy doesn't like that we access the `__init__` property. - client.__init__, # type: ignore[misc] - ) - copy_signature = inspect.signature(client.copy) - exclude_params = {"transport", "proxies", "_strict_response_validation"} - - for name in init_signature.parameters.keys(): - if name in exclude_params: - continue - - copy_param = copy_signature.parameters.get(name) - assert copy_param is not None, f"copy() signature is missing the {name} param" - - @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self, client: Dedalus) -> None: - options = FinalRequestOptions(method="get", url="/foo") - - def build_request(options: FinalRequestOptions) -> None: - client_copy = client.copy() - client_copy._build_request(options) - - # ensure that the machinery is warmed up before tracing starts. - build_request(options) - gc.collect() - - tracemalloc.start(1000) - - snapshot_before = tracemalloc.take_snapshot() - - ITERATIONS = 10 - for _ in range(ITERATIONS): - build_request(options) - - gc.collect() - snapshot_after = tracemalloc.take_snapshot() - - tracemalloc.stop() - - def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.StatisticDiff) -> None: - if diff.count == 0: - # Avoid false positives by considering only leaks (i.e. allocations that persist). - return - - if diff.count % ITERATIONS != 0: - # Avoid false positives by considering only leaks that appear per iteration. - return - - for frame in diff.traceback: - if any( - frame.filename.endswith(fragment) - for fragment in [ - # to_raw_response_wrapper leaks through the @functools.wraps() decorator. - # - # removing the decorator fixes the leak for reasons we don't understand. - "dedalus_sdk/_legacy_response.py", - "dedalus_sdk/_response.py", - # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. - "dedalus_sdk/_compat.py", - # Standard library leaks we don't care about. - "/logging/__init__.py", - ] - ): - return - - leaks.append(diff) - - leaks: list[tracemalloc.StatisticDiff] = [] - for diff in snapshot_after.compare_to(snapshot_before, "traceback"): - add_leak(leaks, diff) - if leaks: - for leak in leaks: - print("MEMORY LEAK:", leak) - for frame in leak.traceback: - print(frame) - raise AssertionError() - - def test_request_timeout(self, client: Dedalus) -> None: - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT - - request = client._build_request(FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0))) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(100.0) - - def test_client_timeout_option(self) -> None: - client = Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0)) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(0) - - client.close() - - def test_http_client_timeout_option(self) -> None: - # custom timeout given to the httpx client should be used - with httpx.Client(timeout=None) as http_client: - client = Dedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(None) - - client.close() - - # no timeout given to the httpx client should not use the httpx default - with httpx.Client() as http_client: - client = Dedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT - - client.close() - - # explicitly passing the default timeout currently results in it being ignored - with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = Dedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT # our default - - client.close() - - async def test_invalid_http_client(self) -> None: - with pytest.raises(TypeError, match="Invalid `http_client` arg"): - async with httpx.AsyncClient() as http_client: - Dedalus( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=cast(Any, http_client), - ) - - def test_default_headers_option(self) -> None: - test_client = Dedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "bar" - assert request.headers.get("x-stainless-lang") == "python" - - test_client2 = Dedalus( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - default_headers={ - "X-Foo": "stainless", - "X-Stainless-Lang": "my-overriding-header", - }, - ) - request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "stainless" - assert request.headers.get("x-stainless-lang") == "my-overriding-header" - - test_client.close() - test_client2.close() - - def test_validate_headers(self) -> None: - client = Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("Authorization") == f"Bearer {api_key}" - - with update_env(**{"DEDALUS_API_KEY": Omit()}): - client2 = Dedalus(base_url=base_url, api_key=None, _strict_response_validation=True) - - with pytest.raises( - TypeError, - match="Could not resolve authentication method. Expected either x_api_key or api_key to be set. Or for one of the `x-api-key` or `Authorization` headers to be explicitly omitted", - ): - client2._build_request(FinalRequestOptions(method="get", url="/foo")) - - request2 = client2._build_request( - FinalRequestOptions(method="get", url="/foo", headers={"Authorization": Omit()}) - ) - assert request2.headers.get("Authorization") is None - - def test_default_query_option(self) -> None: - client = Dedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} - ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - url = httpx.URL(request.url) - assert dict(url.params) == {"query_param": "bar"} - - request = client._build_request( - FinalRequestOptions( - method="get", - url="/foo", - params={"foo": "baz", "query_param": "overridden"}, - ) - ) - url = httpx.URL(request.url) - assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - - client.close() - - def test_hardcoded_query_params_in_url(self, client: Dedalus) -> None: - request = client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) - url = httpx.URL(request.url) - assert dict(url.params) == {"beta": "true"} - - request = client._build_request( - FinalRequestOptions( - method="get", - url="/foo?beta=true", - params={"limit": "10", "page": "abc"}, - ) - ) - url = httpx.URL(request.url) - assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} - - request = client._build_request( - FinalRequestOptions( - method="get", - url="/files/a%2Fb?beta=true", - params={"limit": "10"}, - ) - ) - assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" - - def test_request_extra_json(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar"}, - extra_json={"baz": False}, - ), - ) - data = json.loads(request.content.decode("utf-8")) - assert data == {"foo": "bar", "baz": False} - - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - extra_json={"baz": False}, - ), - ) - data = json.loads(request.content.decode("utf-8")) - assert data == {"baz": False} - - # `extra_json` takes priority over `json_data` when keys clash - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar", "baz": True}, - extra_json={"baz": None}, - ), - ) - data = json.loads(request.content.decode("utf-8")) - assert data == {"foo": "bar", "baz": None} - - def test_request_extra_headers(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options(extra_headers={"X-Foo": "Foo"}), - ), - ) - assert request.headers.get("X-Foo") == "Foo" - - # `extra_headers` takes priority over `default_headers` when keys clash - request = client.with_options(default_headers={"X-Bar": "true"})._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - extra_headers={"X-Bar": "false"}, - ), - ), - ) - assert request.headers.get("X-Bar") == "false" - - def test_request_extra_query(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - extra_query={"my_query_param": "Foo"}, - ), - ), - ) - params = dict(request.url.params) - assert params == {"my_query_param": "Foo"} - - # if both `query` and `extra_query` are given, they are merged - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - query={"bar": "1"}, - extra_query={"foo": "2"}, - ), - ), - ) - params = dict(request.url.params) - assert params == {"bar": "1", "foo": "2"} - - # `extra_query` takes priority over `query` when keys clash - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - query={"foo": "1"}, - extra_query={"foo": "2"}, - ), - ), - ) - params = dict(request.url.params) - assert params == {"foo": "2"} - - def test_multipart_repeating_array(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions.construct( - method="post", - url="/foo", - headers={"Content-Type": "multipart/form-data; boundary=6b7ba517decee4a450543ea6ae821c82"}, - json_data={"array": ["foo", "bar"]}, - files=[("foo.txt", b"hello world")], - ) - ) - - assert request.read().split(b"\r\n") == [ - b"--6b7ba517decee4a450543ea6ae821c82", - b'Content-Disposition: form-data; name="array[]"', - b"", - b"foo", - b"--6b7ba517decee4a450543ea6ae821c82", - b'Content-Disposition: form-data; name="array[]"', - b"", - b"bar", - b"--6b7ba517decee4a450543ea6ae821c82", - b'Content-Disposition: form-data; name="foo.txt"; filename="upload"', - b"Content-Type: application/octet-stream", - b"", - b"hello world", - b"--6b7ba517decee4a450543ea6ae821c82--", - b"", - ] - - @pytest.mark.respx(base_url=base_url) - def test_binary_content_upload(self, respx_mock: MockRouter, client: Dedalus) -> None: - respx_mock.post("/upload").mock(side_effect=mirror_request_content) - - file_content = b"Hello, this is a test file." - - response = client.post( - "/upload", - content=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) - - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - - def test_binary_content_upload_with_iterator(self) -> None: - file_content = b"Hello, this is a test file." - counter = Counter() - iterator = _make_sync_iterator([file_content], counter=counter) - - def mock_handler(request: httpx.Request) -> httpx.Response: - assert counter.value == 0, "the request body should not have been read" - return httpx.Response(200, content=request.read()) - - with Dedalus( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(transport=MockTransport(handler=mock_handler)), - ) as client: - response = client.post( - "/upload", - content=iterator, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) - - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - assert counter.value == 1 - - @pytest.mark.respx(base_url=base_url) - def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, client: Dedalus) -> None: - respx_mock.post("/upload").mock(side_effect=mirror_request_content) - - file_content = b"Hello, this is a test file." - - with pytest.deprecated_call( - match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." - ): - response = client.post( - "/upload", - body=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) - - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - - @pytest.mark.respx(base_url=base_url) - def test_basic_union_response(self, respx_mock: MockRouter, client: Dedalus) -> None: - class Model1(BaseModel): - name: str - - class Model2(BaseModel): - foo: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) - assert isinstance(response, Model2) - assert response.foo == "bar" - - @pytest.mark.respx(base_url=base_url) - def test_union_response_different_types(self, respx_mock: MockRouter, client: Dedalus) -> None: - """Union of objects with the same field name using a different type""" - - class Model1(BaseModel): - foo: int - - class Model2(BaseModel): - foo: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) - assert isinstance(response, Model2) - assert response.foo == "bar" - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - - response = client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) - assert isinstance(response, Model1) - assert response.foo == 1 - - @pytest.mark.respx(base_url=base_url) - def test_non_application_json_content_type_for_json_data(self, respx_mock: MockRouter, client: Dedalus) -> None: - """ - Response that sets Content-Type to something other than application/json but returns json data - """ - - class Model(BaseModel): - foo: int - - respx_mock.get("/foo").mock( - return_value=httpx.Response( - 200, - content=json.dumps({"foo": 2}), - headers={"Content-Type": "application/text"}, - ) - ) - - response = client.get("/foo", cast_to=Model) - assert isinstance(response, Model) - assert response.foo == 2 - - @pytest.mark.respx(base_url=base_url) - def test_idempotency_header_options(self, respx_mock: MockRouter, client: Dedalus) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={})) - - response = client.post("/foo", cast_to=httpx.Response) - - header = response.request.headers.get("Idempotency-Key") - assert header is not None - assert header.startswith("stainless-python-retry") - - # explicit header - response = client.post( - "/foo", - cast_to=httpx.Response, - options=make_request_options(extra_headers={"Idempotency-Key": "custom-key"}), - ) - assert response.request.headers.get("Idempotency-Key") == "custom-key" - - response = client.post( - "/foo", - cast_to=httpx.Response, - options=make_request_options(extra_headers={"idempotency-key": "custom-key"}), - ) - assert response.request.headers.get("Idempotency-Key") == "custom-key" - - # custom argument - response = client.post( - "/foo", cast_to=httpx.Response, options=make_request_options(idempotency_key="custom-key") - ) - assert response.request.headers.get("Idempotency-Key") == "custom-key" - - def test_base_url_setter(self) -> None: - client = Dedalus(base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True) - assert client.base_url == "https://example.com/from_init/" - - client.base_url = "https://example.com/from_setter" # type: ignore[assignment] - - assert client.base_url == "https://example.com/from_setter/" - - client.close() - - def test_base_url_env(self) -> None: - with update_env(DEDALUS_BASE_URL="http://localhost:5000/from/env"): - client = Dedalus(api_key=api_key, _strict_response_validation=True) - assert client.base_url == "http://localhost:5000/from/env/" - - @pytest.mark.parametrize( - "client", - [ - Dedalus(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - Dedalus( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(), - ), - ], - ids=["standard", "custom http client"], - ) - def test_base_url_trailing_slash(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar"}, - ), - ) - assert request.url == "http://localhost:5000/custom/path/foo" - client.close() - - @pytest.mark.parametrize( - "client", - [ - Dedalus(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - Dedalus( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(), - ), - ], - ids=["standard", "custom http client"], - ) - def test_base_url_no_trailing_slash(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar"}, - ), - ) - assert request.url == "http://localhost:5000/custom/path/foo" - client.close() - - @pytest.mark.parametrize( - "client", - [ - Dedalus(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), - Dedalus( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.Client(), - ), - ], - ids=["standard", "custom http client"], - ) - def test_absolute_request_url(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="https://myapi.com/foo", - json_data={"foo": "bar"}, - ), - ) - assert request.url == "https://myapi.com/foo" - client.close() - - def test_copied_client_does_not_close_http(self) -> None: - test_client = Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - assert not test_client.is_closed() - - copied = test_client.copy() - assert copied is not test_client - - del copied - - assert not test_client.is_closed() - - def test_client_context_manager(self) -> None: - test_client = Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - with test_client as c2: - assert c2 is test_client - assert not c2.is_closed() - assert not test_client.is_closed() - assert test_client.is_closed() - - @pytest.mark.respx(base_url=base_url) - def test_client_response_validation_error(self, respx_mock: MockRouter, client: Dedalus) -> None: - class Model(BaseModel): - foo: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) - - with pytest.raises(APIResponseValidationError) as exc: - client.get("/foo", cast_to=Model) - - assert isinstance(exc.value.__cause__, ValidationError) - - def test_client_max_retries_validation(self) -> None: - with pytest.raises(TypeError, match=r"max_retries cannot be None"): - Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) - - @pytest.mark.respx(base_url=base_url) - def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: - class Model(BaseModel): - name: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) - - strict_client = Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - - with pytest.raises(APIResponseValidationError): - strict_client.get("/foo", cast_to=Model) - - non_strict_client = Dedalus(base_url=base_url, api_key=api_key, _strict_response_validation=False) - - response = non_strict_client.get("/foo", cast_to=Model) - assert isinstance(response, str) # type: ignore[unreachable] - - strict_client.close() - non_strict_client.close() - - @pytest.mark.parametrize( - "remaining_retries,retry_after,timeout", - [ - [3, "20", 20], - [3, "0", 0.5], - [3, "-10", 0.5], - [3, "60", 60], - [3, "61", 0.5], - [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], - [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], - [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], - [3, "99999999999999999999999999999999999", 0.5], - [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "", 0.5], - [2, "", 0.5 * 2.0], - [1, "", 0.5 * 4.0], - [-1100, "", 8], # test large number potentially overflowing - ], - ) - @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - def test_parse_retry_after_header( - self, remaining_retries: int, retry_after: str, timeout: float, client: Dedalus - ) -> None: - headers = httpx.Headers({"retry-after": retry_after}) - options = FinalRequestOptions(method="get", url="/foo", max_retries=3) - calculated = client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] - - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: Dedalus) -> None: - respx_mock.post("/v1/machines").mock(side_effect=httpx.TimeoutException("Test timeout error")) - - with pytest.raises(APITimeoutError): - client.machines.with_streaming_response.create().__enter__() - - assert _get_open_connections(client) == 0 - - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: Dedalus) -> None: - respx_mock.post("/v1/machines").mock(return_value=httpx.Response(500)) - - with pytest.raises(APIStatusError): - client.machines.with_streaming_response.create().__enter__() - assert _get_open_connections(client) == 0 - - @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - @pytest.mark.parametrize("failure_mode", ["status", "exception"]) - def test_retries_taken( - self, - client: Dedalus, - failures_before_success: int, - failure_mode: Literal["status", "exception"], - respx_mock: MockRouter, - ) -> None: - client = client.with_options(max_retries=4) - - nb_retries = 0 - - def retry_handler(_request: httpx.Request) -> httpx.Response: - nonlocal nb_retries - if nb_retries < failures_before_success: - nb_retries += 1 - if failure_mode == "exception": - raise RuntimeError("oops") - return httpx.Response(500) - return httpx.Response(200) - - respx_mock.post("/v1/machines").mock(side_effect=retry_handler) - - response = client.machines.with_raw_response.create() - - assert response.retries_taken == failures_before_success - assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success - - @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - def test_omit_retry_count_header( - self, client: Dedalus, failures_before_success: int, respx_mock: MockRouter - ) -> None: - client = client.with_options(max_retries=4) - - nb_retries = 0 - - def retry_handler(_request: httpx.Request) -> httpx.Response: - nonlocal nb_retries - if nb_retries < failures_before_success: - nb_retries += 1 - return httpx.Response(500) - return httpx.Response(200) - - respx_mock.post("/v1/machines").mock(side_effect=retry_handler) - - response = client.machines.with_raw_response.create(extra_headers={"x-stainless-retry-count": Omit()}) - - assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 - - @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - def test_overwrite_retry_count_header( - self, client: Dedalus, failures_before_success: int, respx_mock: MockRouter - ) -> None: - client = client.with_options(max_retries=4) - - nb_retries = 0 - - def retry_handler(_request: httpx.Request) -> httpx.Response: - nonlocal nb_retries - if nb_retries < failures_before_success: - nb_retries += 1 - return httpx.Response(500) - return httpx.Response(200) - - respx_mock.post("/v1/machines").mock(side_effect=retry_handler) - - response = client.machines.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"}) - - assert response.http_request.headers.get("x-stainless-retry-count") == "42" - - def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: - # Test that the proxy environment variables are set correctly - monkeypatch.setenv("HTTPS_PROXY", "https://example.org") - # Delete in case our environment has any proxy env vars set - monkeypatch.delenv("HTTP_PROXY", raising=False) - monkeypatch.delenv("ALL_PROXY", raising=False) - monkeypatch.delenv("NO_PROXY", raising=False) - monkeypatch.delenv("http_proxy", raising=False) - monkeypatch.delenv("https_proxy", raising=False) - monkeypatch.delenv("all_proxy", raising=False) - monkeypatch.delenv("no_proxy", raising=False) - - client = DefaultHttpxClient() - - mounts = tuple(client._mounts.items()) - assert len(mounts) == 1 - assert mounts[0][0].pattern == "https://" - - @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") - def test_default_client_creation(self) -> None: - # Ensure that the client can be initialized without any exceptions - DefaultHttpxClient( - verify=True, - cert=None, - trust_env=True, - http1=True, - http2=False, - limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), - ) - - @pytest.mark.respx(base_url=base_url) - def test_follow_redirects(self, respx_mock: MockRouter, client: Dedalus) -> None: - # Test that the default follow_redirects=True allows following redirects - respx_mock.post("/redirect").mock( - return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) - ) - respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - - response = client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) - assert response.status_code == 200 - assert response.json() == {"status": "ok"} - - @pytest.mark.respx(base_url=base_url) - def test_follow_redirects_disabled(self, respx_mock: MockRouter, client: Dedalus) -> None: - # Test that follow_redirects=False prevents following redirects - respx_mock.post("/redirect").mock( - return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) - ) - - with pytest.raises(APIStatusError) as exc_info: - client.post("/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response) - - assert exc_info.value.response.status_code == 302 - assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" - - -class TestAsyncDedalus: - @pytest.mark.respx(base_url=base_url) - async def test_raw_response(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - response = await async_client.post("/foo", cast_to=httpx.Response) - assert response.status_code == 200 - assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} - - @pytest.mark.respx(base_url=base_url) - async def test_raw_response_for_binary(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - respx_mock.post("/foo").mock( - return_value=httpx.Response(200, headers={"Content-Type": "application/binary"}, content='{"foo": "bar"}') - ) - - response = await async_client.post("/foo", cast_to=httpx.Response) - assert response.status_code == 200 - assert isinstance(response, httpx.Response) - assert response.json() == {"foo": "bar"} - - def test_copy(self, async_client: AsyncDedalus) -> None: - copied = async_client.copy() - assert id(copied) != id(async_client) - - copied = async_client.copy(api_key="another My API Key") - assert copied.api_key == "another My API Key" - assert async_client.api_key == "My API Key" - - def test_copy_default_options(self, async_client: AsyncDedalus) -> None: - # options that have a default are overridden correctly - copied = async_client.copy(max_retries=7) - assert copied.max_retries == 7 - assert async_client.max_retries == 2 - - copied2 = copied.copy(max_retries=6) - assert copied2.max_retries == 6 - assert copied.max_retries == 7 - - # timeout - assert isinstance(async_client.timeout, httpx.Timeout) - copied = async_client.copy(timeout=None) - assert copied.timeout is None - assert isinstance(async_client.timeout, httpx.Timeout) - - async def test_copy_default_headers(self) -> None: - client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - assert client.default_headers["X-Foo"] == "bar" - - # does not override the already given value when not specified - copied = client.copy() - assert copied.default_headers["X-Foo"] == "bar" - - # merges already given headers - copied = client.copy(default_headers={"X-Bar": "stainless"}) - assert copied.default_headers["X-Foo"] == "bar" - assert copied.default_headers["X-Bar"] == "stainless" - - # uses new values for any already given headers - copied = client.copy(default_headers={"X-Foo": "stainless"}) - assert copied.default_headers["X-Foo"] == "stainless" - - # set_default_headers - - # completely overrides already set values - copied = client.copy(set_default_headers={}) - assert copied.default_headers.get("X-Foo") is None - - copied = client.copy(set_default_headers={"X-Bar": "Robert"}) - assert copied.default_headers["X-Bar"] == "Robert" - - with pytest.raises( - ValueError, - match="`default_headers` and `set_default_headers` arguments are mutually exclusive", - ): - client.copy(set_default_headers={}, default_headers={"X-Foo": "Bar"}) - await client.close() - - async def test_copy_default_query(self) -> None: - client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} - ) - assert _get_params(client)["foo"] == "bar" - - # does not override the already given value when not specified - copied = client.copy() - assert _get_params(copied)["foo"] == "bar" - - # merges already given params - copied = client.copy(default_query={"bar": "stainless"}) - params = _get_params(copied) - assert params["foo"] == "bar" - assert params["bar"] == "stainless" - - # uses new values for any already given headers - copied = client.copy(default_query={"foo": "stainless"}) - assert _get_params(copied)["foo"] == "stainless" - - # set_default_query - - # completely overrides already set values - copied = client.copy(set_default_query={}) - assert _get_params(copied) == {} - - copied = client.copy(set_default_query={"bar": "Robert"}) - assert _get_params(copied)["bar"] == "Robert" - - with pytest.raises( - ValueError, - # TODO: update - match="`default_query` and `set_default_query` arguments are mutually exclusive", - ): - client.copy(set_default_query={}, default_query={"foo": "Bar"}) - - await client.close() - - def test_copy_signature(self, async_client: AsyncDedalus) -> None: - # ensure the same parameters that can be passed to the client are defined in the `.copy()` method - init_signature = inspect.signature( - # mypy doesn't like that we access the `__init__` property. - async_client.__init__, # type: ignore[misc] - ) - copy_signature = inspect.signature(async_client.copy) - exclude_params = {"transport", "proxies", "_strict_response_validation"} - - for name in init_signature.parameters.keys(): - if name in exclude_params: - continue - - copy_param = copy_signature.parameters.get(name) - assert copy_param is not None, f"copy() signature is missing the {name} param" - - @pytest.mark.skipif(sys.version_info >= (3, 10), reason="fails because of a memory leak that started from 3.12") - def test_copy_build_request(self, async_client: AsyncDedalus) -> None: - options = FinalRequestOptions(method="get", url="/foo") - - def build_request(options: FinalRequestOptions) -> None: - client_copy = async_client.copy() - client_copy._build_request(options) - - # ensure that the machinery is warmed up before tracing starts. - build_request(options) - gc.collect() - - tracemalloc.start(1000) - - snapshot_before = tracemalloc.take_snapshot() - - ITERATIONS = 10 - for _ in range(ITERATIONS): - build_request(options) - - gc.collect() - snapshot_after = tracemalloc.take_snapshot() - - tracemalloc.stop() - - def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.StatisticDiff) -> None: - if diff.count == 0: - # Avoid false positives by considering only leaks (i.e. allocations that persist). - return - - if diff.count % ITERATIONS != 0: - # Avoid false positives by considering only leaks that appear per iteration. - return - - for frame in diff.traceback: - if any( - frame.filename.endswith(fragment) - for fragment in [ - # to_raw_response_wrapper leaks through the @functools.wraps() decorator. - # - # removing the decorator fixes the leak for reasons we don't understand. - "dedalus_sdk/_legacy_response.py", - "dedalus_sdk/_response.py", - # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. - "dedalus_sdk/_compat.py", - # Standard library leaks we don't care about. - "/logging/__init__.py", - ] - ): - return - - leaks.append(diff) - - leaks: list[tracemalloc.StatisticDiff] = [] - for diff in snapshot_after.compare_to(snapshot_before, "traceback"): - add_leak(leaks, diff) - if leaks: - for leak in leaks: - print("MEMORY LEAK:", leak) - for frame in leak.traceback: - print(frame) - raise AssertionError() - - async def test_request_timeout(self, async_client: AsyncDedalus) -> None: - request = async_client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT - - request = async_client._build_request( - FinalRequestOptions(method="get", url="/foo", timeout=httpx.Timeout(100.0)) - ) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(100.0) - - async def test_client_timeout_option(self) -> None: - client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) - ) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(0) - - await client.close() - - async def test_http_client_timeout_option(self) -> None: - # custom timeout given to the httpx client should be used - async with httpx.AsyncClient(timeout=None) as http_client: - client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == httpx.Timeout(None) - - await client.close() - - # no timeout given to the httpx client should not use the httpx default - async with httpx.AsyncClient() as http_client: - client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT - - await client.close() - - # explicitly passing the default timeout currently results in it being ignored - async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: - client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client - ) - - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - timeout = httpx.Timeout(**request.extensions["timeout"]) # type: ignore - assert timeout == DEFAULT_TIMEOUT # our default - - await client.close() - - def test_invalid_http_client(self) -> None: - with pytest.raises(TypeError, match="Invalid `http_client` arg"): - with httpx.Client() as http_client: - AsyncDedalus( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=cast(Any, http_client), - ) - - async def test_default_headers_option(self) -> None: - test_client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} - ) - request = test_client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "bar" - assert request.headers.get("x-stainless-lang") == "python" - - test_client2 = AsyncDedalus( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - default_headers={ - "X-Foo": "stainless", - "X-Stainless-Lang": "my-overriding-header", - }, - ) - request = test_client2._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-foo") == "stainless" - assert request.headers.get("x-stainless-lang") == "my-overriding-header" - - await test_client.close() - await test_client2.close() - - def test_validate_headers(self) -> None: - client = AsyncDedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("Authorization") == f"Bearer {api_key}" - - with update_env(**{"DEDALUS_API_KEY": Omit()}): - client2 = AsyncDedalus(base_url=base_url, api_key=None, _strict_response_validation=True) - - with pytest.raises( - TypeError, - match="Could not resolve authentication method. Expected either x_api_key or api_key to be set. Or for one of the `x-api-key` or `Authorization` headers to be explicitly omitted", - ): - client2._build_request(FinalRequestOptions(method="get", url="/foo")) - - request2 = client2._build_request( - FinalRequestOptions(method="get", url="/foo", headers={"Authorization": Omit()}) - ) - assert request2.headers.get("Authorization") is None - - async def test_default_query_option(self) -> None: - client = AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} - ) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - url = httpx.URL(request.url) - assert dict(url.params) == {"query_param": "bar"} - - request = client._build_request( - FinalRequestOptions( - method="get", - url="/foo", - params={"foo": "baz", "query_param": "overridden"}, - ) - ) - url = httpx.URL(request.url) - assert dict(url.params) == {"foo": "baz", "query_param": "overridden"} - - await client.close() - - async def test_hardcoded_query_params_in_url(self, async_client: AsyncDedalus) -> None: - request = async_client._build_request(FinalRequestOptions(method="get", url="/foo?beta=true")) - url = httpx.URL(request.url) - assert dict(url.params) == {"beta": "true"} - - request = async_client._build_request( - FinalRequestOptions( - method="get", - url="/foo?beta=true", - params={"limit": "10", "page": "abc"}, - ) - ) - url = httpx.URL(request.url) - assert dict(url.params) == {"beta": "true", "limit": "10", "page": "abc"} - - request = async_client._build_request( - FinalRequestOptions( - method="get", - url="/files/a%2Fb?beta=true", - params={"limit": "10"}, - ) - ) - assert request.url.raw_path == b"/files/a%2Fb?beta=true&limit=10" - - def test_request_extra_json(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar"}, - extra_json={"baz": False}, - ), - ) - data = json.loads(request.content.decode("utf-8")) - assert data == {"foo": "bar", "baz": False} - - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - extra_json={"baz": False}, - ), - ) - data = json.loads(request.content.decode("utf-8")) - assert data == {"baz": False} - - # `extra_json` takes priority over `json_data` when keys clash - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar", "baz": True}, - extra_json={"baz": None}, - ), - ) - data = json.loads(request.content.decode("utf-8")) - assert data == {"foo": "bar", "baz": None} - - def test_request_extra_headers(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options(extra_headers={"X-Foo": "Foo"}), - ), - ) - assert request.headers.get("X-Foo") == "Foo" - - # `extra_headers` takes priority over `default_headers` when keys clash - request = client.with_options(default_headers={"X-Bar": "true"})._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - extra_headers={"X-Bar": "false"}, - ), - ), - ) - assert request.headers.get("X-Bar") == "false" - - def test_request_extra_query(self, client: Dedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - extra_query={"my_query_param": "Foo"}, - ), - ), - ) - params = dict(request.url.params) - assert params == {"my_query_param": "Foo"} - - # if both `query` and `extra_query` are given, they are merged - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - query={"bar": "1"}, - extra_query={"foo": "2"}, - ), - ), - ) - params = dict(request.url.params) - assert params == {"bar": "1", "foo": "2"} - - # `extra_query` takes priority over `query` when keys clash - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - **make_request_options( - query={"foo": "1"}, - extra_query={"foo": "2"}, - ), - ), - ) - params = dict(request.url.params) - assert params == {"foo": "2"} - - def test_multipart_repeating_array(self, async_client: AsyncDedalus) -> None: - request = async_client._build_request( - FinalRequestOptions.construct( - method="post", - url="/foo", - headers={"Content-Type": "multipart/form-data; boundary=6b7ba517decee4a450543ea6ae821c82"}, - json_data={"array": ["foo", "bar"]}, - files=[("foo.txt", b"hello world")], - ) - ) - - assert request.read().split(b"\r\n") == [ - b"--6b7ba517decee4a450543ea6ae821c82", - b'Content-Disposition: form-data; name="array[]"', - b"", - b"foo", - b"--6b7ba517decee4a450543ea6ae821c82", - b'Content-Disposition: form-data; name="array[]"', - b"", - b"bar", - b"--6b7ba517decee4a450543ea6ae821c82", - b'Content-Disposition: form-data; name="foo.txt"; filename="upload"', - b"Content-Type: application/octet-stream", - b"", - b"hello world", - b"--6b7ba517decee4a450543ea6ae821c82--", - b"", - ] - - @pytest.mark.respx(base_url=base_url) - async def test_binary_content_upload(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - respx_mock.post("/upload").mock(side_effect=mirror_request_content) - - file_content = b"Hello, this is a test file." - - response = await async_client.post( - "/upload", - content=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) - - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - - async def test_binary_content_upload_with_asynciterator(self) -> None: - file_content = b"Hello, this is a test file." - counter = Counter() - iterator = _make_async_iterator([file_content], counter=counter) - - async def mock_handler(request: httpx.Request) -> httpx.Response: - assert counter.value == 0, "the request body should not have been read" - return httpx.Response(200, content=await request.aread()) - - async with AsyncDedalus( - base_url=base_url, - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(transport=MockTransport(handler=mock_handler)), - ) as client: - response = await client.post( - "/upload", - content=iterator, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) - - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - assert counter.value == 1 - - @pytest.mark.respx(base_url=base_url) - async def test_binary_content_upload_with_body_is_deprecated( - self, respx_mock: MockRouter, async_client: AsyncDedalus - ) -> None: - respx_mock.post("/upload").mock(side_effect=mirror_request_content) - - file_content = b"Hello, this is a test file." - - with pytest.deprecated_call( - match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." - ): - response = await async_client.post( - "/upload", - body=file_content, - cast_to=httpx.Response, - options={"headers": {"Content-Type": "application/octet-stream"}}, - ) - - assert response.status_code == 200 - assert response.request.headers["Content-Type"] == "application/octet-stream" - assert response.content == file_content - - @pytest.mark.respx(base_url=base_url) - async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - class Model1(BaseModel): - name: str - - class Model2(BaseModel): - foo: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) - assert isinstance(response, Model2) - assert response.foo == "bar" - - @pytest.mark.respx(base_url=base_url) - async def test_union_response_different_types(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - """Union of objects with the same field name using a different type""" - - class Model1(BaseModel): - foo: int - - class Model2(BaseModel): - foo: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - - response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) - assert isinstance(response, Model2) - assert response.foo == "bar" - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": 1})) - - response = await async_client.get("/foo", cast_to=cast(Any, Union[Model1, Model2])) - assert isinstance(response, Model1) - assert response.foo == 1 - - @pytest.mark.respx(base_url=base_url) - async def test_non_application_json_content_type_for_json_data( - self, respx_mock: MockRouter, async_client: AsyncDedalus - ) -> None: - """ - Response that sets Content-Type to something other than application/json but returns json data - """ - - class Model(BaseModel): - foo: int - - respx_mock.get("/foo").mock( - return_value=httpx.Response( - 200, - content=json.dumps({"foo": 2}), - headers={"Content-Type": "application/text"}, - ) - ) - - response = await async_client.get("/foo", cast_to=Model) - assert isinstance(response, Model) - assert response.foo == 2 - - @pytest.mark.respx(base_url=base_url) - async def test_idempotency_header_options(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - respx_mock.post("/foo").mock(return_value=httpx.Response(200, json={})) - - response = await async_client.post("/foo", cast_to=httpx.Response) - - header = response.request.headers.get("Idempotency-Key") - assert header is not None - assert header.startswith("stainless-python-retry") - - # explicit header - response = await async_client.post( - "/foo", - cast_to=httpx.Response, - options=make_request_options(extra_headers={"Idempotency-Key": "custom-key"}), - ) - assert response.request.headers.get("Idempotency-Key") == "custom-key" - - response = await async_client.post( - "/foo", - cast_to=httpx.Response, - options=make_request_options(extra_headers={"idempotency-key": "custom-key"}), - ) - assert response.request.headers.get("Idempotency-Key") == "custom-key" - - # custom argument - response = await async_client.post( - "/foo", cast_to=httpx.Response, options=make_request_options(idempotency_key="custom-key") - ) - assert response.request.headers.get("Idempotency-Key") == "custom-key" - - async def test_base_url_setter(self) -> None: - client = AsyncDedalus( - base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True - ) - assert client.base_url == "https://example.com/from_init/" - - client.base_url = "https://example.com/from_setter" # type: ignore[assignment] - - assert client.base_url == "https://example.com/from_setter/" - - await client.close() - - async def test_base_url_env(self) -> None: - with update_env(DEDALUS_BASE_URL="http://localhost:5000/from/env"): - client = AsyncDedalus(api_key=api_key, _strict_response_validation=True) - assert client.base_url == "http://localhost:5000/from/env/" - - @pytest.mark.parametrize( - "client", - [ - AsyncDedalus( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True - ), - AsyncDedalus( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(), - ), - ], - ids=["standard", "custom http client"], - ) - async def test_base_url_trailing_slash(self, client: AsyncDedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar"}, - ), - ) - assert request.url == "http://localhost:5000/custom/path/foo" - await client.close() - - @pytest.mark.parametrize( - "client", - [ - AsyncDedalus( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True - ), - AsyncDedalus( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(), - ), - ], - ids=["standard", "custom http client"], - ) - async def test_base_url_no_trailing_slash(self, client: AsyncDedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="/foo", - json_data={"foo": "bar"}, - ), - ) - assert request.url == "http://localhost:5000/custom/path/foo" - await client.close() - - @pytest.mark.parametrize( - "client", - [ - AsyncDedalus( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True - ), - AsyncDedalus( - base_url="http://localhost:5000/custom/path/", - api_key=api_key, - _strict_response_validation=True, - http_client=httpx.AsyncClient(), - ), - ], - ids=["standard", "custom http client"], - ) - async def test_absolute_request_url(self, client: AsyncDedalus) -> None: - request = client._build_request( - FinalRequestOptions( - method="post", - url="https://myapi.com/foo", - json_data={"foo": "bar"}, - ), - ) - assert request.url == "https://myapi.com/foo" - await client.close() - - async def test_copied_client_does_not_close_http(self) -> None: - test_client = AsyncDedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - assert not test_client.is_closed() - - copied = test_client.copy() - assert copied is not test_client - - del copied - - await asyncio.sleep(0.2) - assert not test_client.is_closed() - - async def test_client_context_manager(self) -> None: - test_client = AsyncDedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - async with test_client as c2: - assert c2 is test_client - assert not c2.is_closed() - assert not test_client.is_closed() - assert test_client.is_closed() - - @pytest.mark.respx(base_url=base_url) - async def test_client_response_validation_error(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - class Model(BaseModel): - foo: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, json={"foo": {"invalid": True}})) - - with pytest.raises(APIResponseValidationError) as exc: - await async_client.get("/foo", cast_to=Model) - - assert isinstance(exc.value.__cause__, ValidationError) - - async def test_client_max_retries_validation(self) -> None: - with pytest.raises(TypeError, match=r"max_retries cannot be None"): - AsyncDedalus( - base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None) - ) - - @pytest.mark.respx(base_url=base_url) - async def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: - class Model(BaseModel): - name: str - - respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) - - strict_client = AsyncDedalus(base_url=base_url, api_key=api_key, _strict_response_validation=True) - - with pytest.raises(APIResponseValidationError): - await strict_client.get("/foo", cast_to=Model) - - non_strict_client = AsyncDedalus(base_url=base_url, api_key=api_key, _strict_response_validation=False) - - response = await non_strict_client.get("/foo", cast_to=Model) - assert isinstance(response, str) # type: ignore[unreachable] - - await strict_client.close() - await non_strict_client.close() - - @pytest.mark.parametrize( - "remaining_retries,retry_after,timeout", - [ - [3, "20", 20], - [3, "0", 0.5], - [3, "-10", 0.5], - [3, "60", 60], - [3, "61", 0.5], - [3, "Fri, 29 Sep 2023 16:26:57 GMT", 20], - [3, "Fri, 29 Sep 2023 16:26:37 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "Fri, 29 Sep 2023 16:27:37 GMT", 60], - [3, "Fri, 29 Sep 2023 16:27:38 GMT", 0.5], - [3, "99999999999999999999999999999999999", 0.5], - [3, "Zun, 29 Sep 2023 16:26:27 GMT", 0.5], - [3, "", 0.5], - [2, "", 0.5 * 2.0], - [1, "", 0.5 * 4.0], - [-1100, "", 8], # test large number potentially overflowing - ], - ) - @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) - async def test_parse_retry_after_header( - self, remaining_retries: int, retry_after: str, timeout: float, async_client: AsyncDedalus - ) -> None: - headers = httpx.Headers({"retry-after": retry_after}) - options = FinalRequestOptions(method="get", url="/foo", max_retries=3) - calculated = async_client._calculate_retry_timeout(remaining_retries, options, headers) - assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] - - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - async def test_retrying_timeout_errors_doesnt_leak( - self, respx_mock: MockRouter, async_client: AsyncDedalus - ) -> None: - respx_mock.post("/v1/machines").mock(side_effect=httpx.TimeoutException("Test timeout error")) - - with pytest.raises(APITimeoutError): - await async_client.machines.with_streaming_response.create().__aenter__() - - assert _get_open_connections(async_client) == 0 - - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - respx_mock.post("/v1/machines").mock(return_value=httpx.Response(500)) - - with pytest.raises(APIStatusError): - await async_client.machines.with_streaming_response.create().__aenter__() - assert _get_open_connections(async_client) == 0 - - @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - @pytest.mark.parametrize("failure_mode", ["status", "exception"]) - async def test_retries_taken( - self, - async_client: AsyncDedalus, - failures_before_success: int, - failure_mode: Literal["status", "exception"], - respx_mock: MockRouter, - ) -> None: - client = async_client.with_options(max_retries=4) - - nb_retries = 0 - - def retry_handler(_request: httpx.Request) -> httpx.Response: - nonlocal nb_retries - if nb_retries < failures_before_success: - nb_retries += 1 - if failure_mode == "exception": - raise RuntimeError("oops") - return httpx.Response(500) - return httpx.Response(200) - - respx_mock.post("/v1/machines").mock(side_effect=retry_handler) - - response = await client.machines.with_raw_response.create() - - assert response.retries_taken == failures_before_success - assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success - - @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - async def test_omit_retry_count_header( - self, async_client: AsyncDedalus, failures_before_success: int, respx_mock: MockRouter - ) -> None: - client = async_client.with_options(max_retries=4) - - nb_retries = 0 - - def retry_handler(_request: httpx.Request) -> httpx.Response: - nonlocal nb_retries - if nb_retries < failures_before_success: - nb_retries += 1 - return httpx.Response(500) - return httpx.Response(200) - - respx_mock.post("/v1/machines").mock(side_effect=retry_handler) - - response = await client.machines.with_raw_response.create(extra_headers={"x-stainless-retry-count": Omit()}) - - assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 - - @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("dedalus_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) - @pytest.mark.respx(base_url=base_url) - async def test_overwrite_retry_count_header( - self, async_client: AsyncDedalus, failures_before_success: int, respx_mock: MockRouter - ) -> None: - client = async_client.with_options(max_retries=4) - - nb_retries = 0 - - def retry_handler(_request: httpx.Request) -> httpx.Response: - nonlocal nb_retries - if nb_retries < failures_before_success: - nb_retries += 1 - return httpx.Response(500) - return httpx.Response(200) - - respx_mock.post("/v1/machines").mock(side_effect=retry_handler) - - response = await client.machines.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"}) - - assert response.http_request.headers.get("x-stainless-retry-count") == "42" - - async def test_get_platform(self) -> None: - platform = await asyncify(get_platform)() - assert isinstance(platform, (str, OtherPlatform)) - - async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None: - # Test that the proxy environment variables are set correctly - monkeypatch.setenv("HTTPS_PROXY", "https://example.org") - # Delete in case our environment has any proxy env vars set - monkeypatch.delenv("HTTP_PROXY", raising=False) - monkeypatch.delenv("ALL_PROXY", raising=False) - monkeypatch.delenv("NO_PROXY", raising=False) - monkeypatch.delenv("http_proxy", raising=False) - monkeypatch.delenv("https_proxy", raising=False) - monkeypatch.delenv("all_proxy", raising=False) - monkeypatch.delenv("no_proxy", raising=False) - - client = DefaultAsyncHttpxClient() - - mounts = tuple(client._mounts.items()) - assert len(mounts) == 1 - assert mounts[0][0].pattern == "https://" - - @pytest.mark.filterwarnings("ignore:.*deprecated.*:DeprecationWarning") - async def test_default_client_creation(self) -> None: - # Ensure that the client can be initialized without any exceptions - DefaultAsyncHttpxClient( - verify=True, - cert=None, - trust_env=True, - http1=True, - http2=False, - limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), - ) - - @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - # Test that the default follow_redirects=True allows following redirects - respx_mock.post("/redirect").mock( - return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) - ) - respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) - - response = await async_client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) - assert response.status_code == 200 - assert response.json() == {"status": "ok"} - - @pytest.mark.respx(base_url=base_url) - async def test_follow_redirects_disabled(self, respx_mock: MockRouter, async_client: AsyncDedalus) -> None: - # Test that follow_redirects=False prevents following redirects - respx_mock.post("/redirect").mock( - return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) - ) - - with pytest.raises(APIStatusError) as exc_info: - await async_client.post( - "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response - ) - - assert exc_info.value.response.status_code == 302 - assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py deleted file mode 100644 index 4b12fbd..0000000 --- a/tests/test_extract_files.py +++ /dev/null @@ -1,91 +0,0 @@ -from __future__ import annotations - -from typing import Sequence - -import pytest - -from dedalus_sdk._types import FileTypes, ArrayFormat -from dedalus_sdk._utils import extract_files - - -def test_removes_files_from_input() -> None: - query = {"foo": "bar"} - assert extract_files(query, paths=[]) == [] - assert query == {"foo": "bar"} - - query2 = {"foo": b"Bar", "hello": "world"} - assert extract_files(query2, paths=[["foo"]]) == [("foo", b"Bar")] - assert query2 == {"hello": "world"} - - query3 = {"foo": {"foo": {"bar": b"Bar"}}, "hello": "world"} - assert extract_files(query3, paths=[["foo", "foo", "bar"]]) == [("foo[foo][bar]", b"Bar")] - assert query3 == {"foo": {"foo": {}}, "hello": "world"} - - query4 = {"foo": {"bar": b"Bar", "baz": "foo"}, "hello": "world"} - assert extract_files(query4, paths=[["foo", "bar"]]) == [("foo[bar]", b"Bar")] - assert query4 == {"hello": "world", "foo": {"baz": "foo"}} - - -def test_multiple_files() -> None: - query = {"documents": [{"file": b"My first file"}, {"file": b"My second file"}]} - assert extract_files(query, paths=[["documents", "", "file"]]) == [ - ("documents[][file]", b"My first file"), - ("documents[][file]", b"My second file"), - ] - assert query == {"documents": [{}, {}]} - - -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 query == {"title": "hello"} - - -@pytest.mark.parametrize( - "query,paths,expected", - [ - [ - {"foo": {"bar": "baz"}}, - [["foo", "", "bar"]], - [], - ], - [ - {"foo": ["bar", "baz"]}, - [["foo", "bar"]], - [], - ], - [ - {"foo": {"bar": "baz"}}, - [["foo", "foo"]], - [], - ], - ], - ids=["dict expecting array", "array expecting dict", "unknown keys"], -) -def test_ignores_incorrect_paths( - query: dict[str, object], - paths: Sequence[Sequence[str]], - 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 deleted file mode 100644 index e1cd7d2..0000000 --- a/tests/test_files.py +++ /dev/null @@ -1,148 +0,0 @@ -from pathlib import Path - -import anyio -import pytest -from dirty_equals import IsDict, IsList, IsBytes, IsTuple - -from dedalus_sdk._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files -from dedalus_sdk._utils import extract_files - -readme_path = Path(__file__).parent.parent.joinpath("README.md") - - -def test_pathlib_includes_file_name() -> None: - result = to_httpx_files({"file": readme_path}) - print(result) - assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) - - -def test_tuple_input() -> None: - result = to_httpx_files([("file", readme_path)]) - print(result) - assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) - - -@pytest.mark.asyncio -async def test_async_pathlib_includes_file_name() -> None: - result = await async_to_httpx_files({"file": readme_path}) - print(result) - assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) - - -@pytest.mark.asyncio -async def test_async_supports_anyio_path() -> None: - result = await async_to_httpx_files({"file": anyio.Path(readme_path)}) - print(result) - assert result == IsDict({"file": IsTuple("README.md", IsBytes())}) - - -@pytest.mark.asyncio -async def test_async_tuple_input() -> None: - result = await async_to_httpx_files([("file", readme_path)]) - print(result) - assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) - - -def test_string_not_allowed() -> None: - with pytest.raises(TypeError, match="Expected file types input to be a FileContent type or to be a tuple"): - to_httpx_files( - { - "file": "foo", # type: ignore - } - ) - - -def assert_different_identities(obj1: object, obj2: object) -> None: - assert obj1 == obj2 - assert obj1 is not obj2 - - -class TestDeepcopyWithPaths: - def test_copies_top_level_dict(self) -> None: - original = {"file": b"data", "other": "value"} - result = deepcopy_with_paths(original, [["file"]]) - assert_different_identities(result, original) - - def test_file_value_is_same_reference(self) -> None: - file_bytes = b"contents" - original = {"file": file_bytes} - result = deepcopy_with_paths(original, [["file"]]) - assert_different_identities(result, original) - assert result["file"] is file_bytes - - def test_list_popped_wholesale(self) -> None: - files = [b"f1", b"f2"] - original = {"files": files, "title": "t"} - result = deepcopy_with_paths(original, [["files", ""]]) - assert_different_identities(result, original) - result_files = result["files"] - assert isinstance(result_files, list) - assert_different_identities(result_files, files) - - def test_nested_array_path_copies_list_and_elements(self) -> None: - elem1 = {"file": b"f1", "extra": 1} - elem2 = {"file": b"f2", "extra": 2} - original = {"items": [elem1, elem2]} - result = deepcopy_with_paths(original, [["items", "", "file"]]) - assert_different_identities(result, original) - result_items = result["items"] - assert isinstance(result_items, list) - assert_different_identities(result_items, original["items"]) - assert_different_identities(result_items[0], elem1) - assert_different_identities(result_items[1], elem2) - - def test_empty_paths_returns_same_object(self) -> None: - original = {"foo": "bar"} - result = deepcopy_with_paths(original, []) - assert result is original - - def test_multiple_paths(self) -> None: - f1 = b"file1" - f2 = b"file2" - original = {"a": f1, "b": f2, "c": "unchanged"} - result = deepcopy_with_paths(original, [["a"], ["b"]]) - assert_different_identities(result, original) - assert result["a"] is f1 - assert result["b"] is f2 - assert result["c"] is original["c"] - - def test_extract_files_does_not_mutate_original_top_level(self) -> None: - file_bytes = b"contents" - original = {"file": file_bytes, "other": "value"} - - copied = deepcopy_with_paths(original, [["file"]]) - extracted = extract_files(copied, paths=[["file"]]) - - assert extracted == [("file", file_bytes)] - assert original == {"file": file_bytes, "other": "value"} - assert copied == {"other": "value"} - - def test_extract_files_does_not_mutate_original_nested_array_path(self) -> None: - file1 = b"f1" - file2 = b"f2" - original = { - "items": [ - {"file": file1, "extra": 1}, - {"file": file2, "extra": 2}, - ], - "title": "example", - } - - copied = deepcopy_with_paths(original, [["items", "", "file"]]) - extracted = extract_files(copied, paths=[["items", "", "file"]]) - - assert [entry for _, entry in extracted] == [file1, file2] - assert original == { - "items": [ - {"file": file1, "extra": 1}, - {"file": file2, "extra": 2}, - ], - "title": "example", - } - assert copied == { - "items": [ - {"extra": 1}, - {"extra": 2}, - ], - "title": "example", - } diff --git a/tests/test_models.py b/tests/test_models.py deleted file mode 100644 index 159c141..0000000 --- a/tests/test_models.py +++ /dev/null @@ -1,1017 +0,0 @@ -import json -from typing import TYPE_CHECKING, Any, Dict, List, Union, Iterable, Optional, cast -from datetime import datetime, timezone -from collections import deque -from typing_extensions import Literal, Annotated, TypedDict, TypeAliasType - -import pytest -import pydantic -from pydantic import Field - -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, EagerIterable, construct_type - - -class BasicModel(BaseModel): - foo: str - - -@pytest.mark.parametrize("value", ["hello", 1], ids=["correct type", "mismatched"]) -def test_basic(value: object) -> None: - m = BasicModel.construct(foo=value) - assert m.foo == value - - -def test_directly_nested_model() -> None: - class NestedModel(BaseModel): - nested: BasicModel - - m = NestedModel.construct(nested={"foo": "Foo!"}) - assert m.nested.foo == "Foo!" - - # mismatched types - m = NestedModel.construct(nested="hello!") - assert cast(Any, m.nested) == "hello!" - - -def test_optional_nested_model() -> None: - class NestedModel(BaseModel): - nested: Optional[BasicModel] - - m1 = NestedModel.construct(nested=None) - assert m1.nested is None - - m2 = NestedModel.construct(nested={"foo": "bar"}) - assert m2.nested is not None - assert m2.nested.foo == "bar" - - # mismatched types - m3 = NestedModel.construct(nested={"foo"}) - assert isinstance(cast(Any, m3.nested), set) - assert cast(Any, m3.nested) == {"foo"} - - -def test_list_nested_model() -> None: - class NestedModel(BaseModel): - nested: List[BasicModel] - - m = NestedModel.construct(nested=[{"foo": "bar"}, {"foo": "2"}]) - assert m.nested is not None - assert isinstance(m.nested, list) - assert len(m.nested) == 2 - assert m.nested[0].foo == "bar" - assert m.nested[1].foo == "2" - - # mismatched types - m = NestedModel.construct(nested=True) - assert cast(Any, m.nested) is True - - m = NestedModel.construct(nested=[False]) - assert cast(Any, m.nested) == [False] - - -def test_optional_list_nested_model() -> None: - class NestedModel(BaseModel): - nested: Optional[List[BasicModel]] - - m1 = NestedModel.construct(nested=[{"foo": "bar"}, {"foo": "2"}]) - assert m1.nested is not None - assert isinstance(m1.nested, list) - assert len(m1.nested) == 2 - assert m1.nested[0].foo == "bar" - assert m1.nested[1].foo == "2" - - m2 = NestedModel.construct(nested=None) - assert m2.nested is None - - # mismatched types - m3 = NestedModel.construct(nested={1}) - assert cast(Any, m3.nested) == {1} - - m4 = NestedModel.construct(nested=[False]) - assert cast(Any, m4.nested) == [False] - - -def test_list_optional_items_nested_model() -> None: - class NestedModel(BaseModel): - nested: List[Optional[BasicModel]] - - m = NestedModel.construct(nested=[None, {"foo": "bar"}]) - assert m.nested is not None - assert isinstance(m.nested, list) - assert len(m.nested) == 2 - assert m.nested[0] is None - assert m.nested[1] is not None - assert m.nested[1].foo == "bar" - - # mismatched types - m3 = NestedModel.construct(nested="foo") - assert cast(Any, m3.nested) == "foo" - - m4 = NestedModel.construct(nested=[False]) - assert cast(Any, m4.nested) == [False] - - -def test_list_mismatched_type() -> None: - class NestedModel(BaseModel): - nested: List[str] - - m = NestedModel.construct(nested=False) - assert cast(Any, m.nested) is False - - -def test_raw_dictionary() -> None: - class NestedModel(BaseModel): - nested: Dict[str, str] - - m = NestedModel.construct(nested={"hello": "world"}) - assert m.nested == {"hello": "world"} - - # mismatched types - m = NestedModel.construct(nested=False) - assert cast(Any, m.nested) is False - - -def test_nested_dictionary_model() -> None: - class NestedModel(BaseModel): - nested: Dict[str, BasicModel] - - m = NestedModel.construct(nested={"hello": {"foo": "bar"}}) - assert isinstance(m.nested, dict) - assert m.nested["hello"].foo == "bar" - - # mismatched types - m = NestedModel.construct(nested={"hello": False}) - assert cast(Any, m.nested["hello"]) is False - - -def test_unknown_fields() -> None: - m1 = BasicModel.construct(foo="foo", unknown=1) - assert m1.foo == "foo" - assert cast(Any, m1).unknown == 1 - - m2 = BasicModel.construct(foo="foo", unknown={"foo_bar": True}) - assert m2.foo == "foo" - assert cast(Any, m2).unknown == {"foo_bar": True} - - assert model_dump(m2) == {"foo": "foo", "unknown": {"foo_bar": True}} - - -def test_strict_validation_unknown_fields() -> None: - class Model(BaseModel): - foo: str - - model = parse_obj(Model, dict(foo="hello!", user="Robert")) - assert model.foo == "hello!" - assert cast(Any, model).user == "Robert" - - assert model_dump(model) == {"foo": "hello!", "user": "Robert"} - - -def test_aliases() -> None: - class Model(BaseModel): - my_field: int = Field(alias="myField") - - m = Model.construct(myField=1) - assert m.my_field == 1 - - # mismatched types - m = Model.construct(myField={"hello": False}) - assert cast(Any, m.my_field) == {"hello": False} - - -def test_repr() -> None: - model = BasicModel(foo="bar") - assert str(model) == "BasicModel(foo='bar')" - assert repr(model) == "BasicModel(foo='bar')" - - -def test_repr_nested_model() -> None: - class Child(BaseModel): - name: str - age: int - - class Parent(BaseModel): - name: str - child: Child - - model = Parent(name="Robert", child=Child(name="Foo", age=5)) - assert str(model) == "Parent(name='Robert', child=Child(name='Foo', age=5))" - assert repr(model) == "Parent(name='Robert', child=Child(name='Foo', age=5))" - - -def test_optional_list() -> None: - class Submodel(BaseModel): - name: str - - class Model(BaseModel): - items: Optional[List[Submodel]] - - m = Model.construct(items=None) - assert m.items is None - - m = Model.construct(items=[]) - assert m.items == [] - - m = Model.construct(items=[{"name": "Robert"}]) - assert m.items is not None - assert len(m.items) == 1 - assert m.items[0].name == "Robert" - - -def test_nested_union_of_models() -> None: - class Submodel1(BaseModel): - bar: bool - - class Submodel2(BaseModel): - thing: str - - class Model(BaseModel): - foo: Union[Submodel1, Submodel2] - - m = Model.construct(foo={"thing": "hello"}) - assert isinstance(m.foo, Submodel2) - assert m.foo.thing == "hello" - - -def test_nested_union_of_mixed_types() -> None: - class Submodel1(BaseModel): - bar: bool - - class Model(BaseModel): - foo: Union[Submodel1, Literal[True], Literal["CARD_HOLDER"]] - - m = Model.construct(foo=True) - assert m.foo is True - - m = Model.construct(foo="CARD_HOLDER") - assert m.foo == "CARD_HOLDER" - - m = Model.construct(foo={"bar": False}) - assert isinstance(m.foo, Submodel1) - assert m.foo.bar is False - - -def test_nested_union_multiple_variants() -> None: - class Submodel1(BaseModel): - bar: bool - - class Submodel2(BaseModel): - thing: str - - class Submodel3(BaseModel): - foo: int - - class Model(BaseModel): - foo: Union[Submodel1, Submodel2, None, Submodel3] - - m = Model.construct(foo={"thing": "hello"}) - assert isinstance(m.foo, Submodel2) - assert m.foo.thing == "hello" - - m = Model.construct(foo=None) - assert m.foo is None - - m = Model.construct() - assert m.foo is None - - m = Model.construct(foo={"foo": "1"}) - assert isinstance(m.foo, Submodel3) - assert m.foo.foo == 1 - - -def test_nested_union_invalid_data() -> None: - class Submodel1(BaseModel): - level: int - - class Submodel2(BaseModel): - name: str - - class Model(BaseModel): - foo: Union[Submodel1, Submodel2] - - m = Model.construct(foo=True) - assert cast(bool, m.foo) is True - - m = Model.construct(foo={"name": 3}) - if PYDANTIC_V1: - assert isinstance(m.foo, Submodel2) - assert m.foo.name == "3" - else: - assert isinstance(m.foo, Submodel1) - assert m.foo.name == 3 # type: ignore - - -def test_list_of_unions() -> None: - class Submodel1(BaseModel): - level: int - - class Submodel2(BaseModel): - name: str - - class Model(BaseModel): - items: List[Union[Submodel1, Submodel2]] - - m = Model.construct(items=[{"level": 1}, {"name": "Robert"}]) - assert len(m.items) == 2 - assert isinstance(m.items[0], Submodel1) - assert m.items[0].level == 1 - assert isinstance(m.items[1], Submodel2) - assert m.items[1].name == "Robert" - - m = Model.construct(items=[{"level": -1}, 156]) - assert len(m.items) == 2 - assert isinstance(m.items[0], Submodel1) - assert m.items[0].level == -1 - assert cast(Any, m.items[1]) == 156 - - -def test_union_of_lists() -> None: - class SubModel1(BaseModel): - level: int - - class SubModel2(BaseModel): - name: str - - class Model(BaseModel): - items: Union[List[SubModel1], List[SubModel2]] - - # with one valid entry - m = Model.construct(items=[{"name": "Robert"}]) - assert len(m.items) == 1 - assert isinstance(m.items[0], SubModel2) - assert m.items[0].name == "Robert" - - # with two entries pointing to different types - m = Model.construct(items=[{"level": 1}, {"name": "Robert"}]) - assert len(m.items) == 2 - assert isinstance(m.items[0], SubModel1) - assert m.items[0].level == 1 - assert isinstance(m.items[1], SubModel1) - assert cast(Any, m.items[1]).name == "Robert" - - # with two entries pointing to *completely* different types - m = Model.construct(items=[{"level": -1}, 156]) - assert len(m.items) == 2 - assert isinstance(m.items[0], SubModel1) - assert m.items[0].level == -1 - assert cast(Any, m.items[1]) == 156 - - -def test_dict_of_union() -> None: - class SubModel1(BaseModel): - name: str - - class SubModel2(BaseModel): - foo: str - - class Model(BaseModel): - data: Dict[str, Union[SubModel1, SubModel2]] - - m = Model.construct(data={"hello": {"name": "there"}, "foo": {"foo": "bar"}}) - assert len(list(m.data.keys())) == 2 - assert isinstance(m.data["hello"], SubModel1) - assert m.data["hello"].name == "there" - assert isinstance(m.data["foo"], SubModel2) - assert m.data["foo"].foo == "bar" - - # TODO: test mismatched type - - -def test_double_nested_union() -> None: - class SubModel1(BaseModel): - name: str - - class SubModel2(BaseModel): - bar: str - - class Model(BaseModel): - data: Dict[str, List[Union[SubModel1, SubModel2]]] - - m = Model.construct(data={"foo": [{"bar": "baz"}, {"name": "Robert"}]}) - assert len(m.data["foo"]) == 2 - - entry1 = m.data["foo"][0] - assert isinstance(entry1, SubModel2) - assert entry1.bar == "baz" - - entry2 = m.data["foo"][1] - assert isinstance(entry2, SubModel1) - assert entry2.name == "Robert" - - # TODO: test mismatched type - - -def test_union_of_dict() -> None: - class SubModel1(BaseModel): - name: str - - class SubModel2(BaseModel): - foo: str - - class Model(BaseModel): - data: Union[Dict[str, SubModel1], Dict[str, SubModel2]] - - m = Model.construct(data={"hello": {"name": "there"}, "foo": {"foo": "bar"}}) - assert len(list(m.data.keys())) == 2 - assert isinstance(m.data["hello"], SubModel1) - assert m.data["hello"].name == "there" - assert isinstance(m.data["foo"], SubModel1) - assert cast(Any, m.data["foo"]).foo == "bar" - - -def test_iso8601_datetime() -> None: - class Model(BaseModel): - created_at: datetime - - expected = datetime(2019, 12, 27, 18, 11, 19, 117000, tzinfo=timezone.utc) - - if PYDANTIC_V1: - expected_json = '{"created_at": "2019-12-27T18:11:19.117000+00:00"}' - else: - expected_json = '{"created_at":"2019-12-27T18:11:19.117000Z"}' - - model = Model.construct(created_at="2019-12-27T18:11:19.117Z") - assert model.created_at == expected - assert model_json(model) == expected_json - - model = parse_obj(Model, dict(created_at="2019-12-27T18:11:19.117Z")) - assert model.created_at == expected - assert model_json(model) == expected_json - - -def test_does_not_coerce_int() -> None: - class Model(BaseModel): - bar: int - - assert Model.construct(bar=1).bar == 1 - assert Model.construct(bar=10.9).bar == 10.9 - assert Model.construct(bar="19").bar == "19" # type: ignore[comparison-overlap] - assert Model.construct(bar=False).bar is False - - -def test_int_to_float_safe_conversion() -> None: - class Model(BaseModel): - float_field: float - - m = Model.construct(float_field=10) - assert m.float_field == 10.0 - assert isinstance(m.float_field, float) - - m = Model.construct(float_field=10.12) - assert m.float_field == 10.12 - assert isinstance(m.float_field, float) - - # number too big - m = Model.construct(float_field=2**53 + 1) - assert m.float_field == 2**53 + 1 - assert isinstance(m.float_field, int) - - -def test_deprecated_alias() -> None: - class Model(BaseModel): - resource_id: str = Field(alias="model_id") - - @property - def model_id(self) -> str: - return self.resource_id - - m = Model.construct(model_id="id") - assert m.model_id == "id" - assert m.resource_id == "id" - assert m.resource_id is m.model_id - - m = parse_obj(Model, {"model_id": "id"}) - assert m.model_id == "id" - assert m.resource_id == "id" - assert m.resource_id is m.model_id - - -def test_omitted_fields() -> None: - class Model(BaseModel): - resource_id: Optional[str] = None - - m = Model.construct() - assert m.resource_id is None - assert "resource_id" not in m.model_fields_set - - m = Model.construct(resource_id=None) - assert m.resource_id is None - assert "resource_id" in m.model_fields_set - - m = Model.construct(resource_id="foo") - assert m.resource_id == "foo" - assert "resource_id" in m.model_fields_set - - -def test_to_dict() -> None: - class Model(BaseModel): - foo: Optional[str] = Field(alias="FOO", default=None) - - m = Model(FOO="hello") - assert m.to_dict() == {"FOO": "hello"} - assert m.to_dict(use_api_names=False) == {"foo": "hello"} - - m2 = Model() - assert m2.to_dict() == {} - assert m2.to_dict(exclude_unset=False) == {"FOO": None} - assert m2.to_dict(exclude_unset=False, exclude_none=True) == {} - assert m2.to_dict(exclude_unset=False, exclude_defaults=True) == {} - - m3 = Model(FOO=None) - assert m3.to_dict() == {"FOO": None} - assert m3.to_dict(exclude_none=True) == {} - assert m3.to_dict(exclude_defaults=True) == {} - - class Model2(BaseModel): - created_at: datetime - - time_str = "2024-03-21T11:39:01.275859" - m4 = Model2.construct(created_at=time_str) - assert m4.to_dict(mode="python") == {"created_at": datetime.fromisoformat(time_str)} - assert m4.to_dict(mode="json") == {"created_at": time_str} - - if PYDANTIC_V1: - with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): - m.to_dict(warnings=False) - - -def test_forwards_compat_model_dump_method() -> None: - class Model(BaseModel): - foo: Optional[str] = Field(alias="FOO", default=None) - - m = Model(FOO="hello") - assert m.model_dump() == {"foo": "hello"} - assert m.model_dump(include={"bar"}) == {} - assert m.model_dump(exclude={"foo"}) == {} - assert m.model_dump(by_alias=True) == {"FOO": "hello"} - - m2 = Model() - assert m2.model_dump() == {"foo": None} - assert m2.model_dump(exclude_unset=True) == {} - assert m2.model_dump(exclude_none=True) == {} - assert m2.model_dump(exclude_defaults=True) == {} - - m3 = Model(FOO=None) - assert m3.model_dump() == {"foo": None} - assert m3.model_dump(exclude_none=True) == {} - - if PYDANTIC_V1: - with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): - m.model_dump(round_trip=True) - - with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): - m.model_dump(warnings=False) - - -def test_compat_method_no_error_for_warnings() -> None: - class Model(BaseModel): - foo: Optional[str] - - m = Model(foo="hello") - assert isinstance(model_dump(m, warnings=False), dict) - - -def test_to_json() -> None: - class Model(BaseModel): - foo: Optional[str] = Field(alias="FOO", default=None) - - m = Model(FOO="hello") - assert json.loads(m.to_json()) == {"FOO": "hello"} - assert json.loads(m.to_json(use_api_names=False)) == {"foo": "hello"} - - if PYDANTIC_V1: - assert m.to_json(indent=None) == '{"FOO": "hello"}' - else: - assert m.to_json(indent=None) == '{"FOO":"hello"}' - - m2 = Model() - assert json.loads(m2.to_json()) == {} - assert json.loads(m2.to_json(exclude_unset=False)) == {"FOO": None} - assert json.loads(m2.to_json(exclude_unset=False, exclude_none=True)) == {} - assert json.loads(m2.to_json(exclude_unset=False, exclude_defaults=True)) == {} - - m3 = Model(FOO=None) - assert json.loads(m3.to_json()) == {"FOO": None} - assert json.loads(m3.to_json(exclude_none=True)) == {} - - if PYDANTIC_V1: - with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): - m.to_json(warnings=False) - - -def test_forwards_compat_model_dump_json_method() -> None: - class Model(BaseModel): - foo: Optional[str] = Field(alias="FOO", default=None) - - m = Model(FOO="hello") - assert json.loads(m.model_dump_json()) == {"foo": "hello"} - assert json.loads(m.model_dump_json(include={"bar"})) == {} - assert json.loads(m.model_dump_json(include={"foo"})) == {"foo": "hello"} - assert json.loads(m.model_dump_json(by_alias=True)) == {"FOO": "hello"} - - assert m.model_dump_json(indent=2) == '{\n "foo": "hello"\n}' - - m2 = Model() - assert json.loads(m2.model_dump_json()) == {"foo": None} - assert json.loads(m2.model_dump_json(exclude_unset=True)) == {} - assert json.loads(m2.model_dump_json(exclude_none=True)) == {} - assert json.loads(m2.model_dump_json(exclude_defaults=True)) == {} - - m3 = Model(FOO=None) - assert json.loads(m3.model_dump_json()) == {"foo": None} - assert json.loads(m3.model_dump_json(exclude_none=True)) == {} - - if PYDANTIC_V1: - with pytest.raises(ValueError, match="round_trip is only supported in Pydantic v2"): - m.model_dump_json(round_trip=True) - - with pytest.raises(ValueError, match="warnings is only supported in Pydantic v2"): - m.model_dump_json(warnings=False) - - -def test_type_compat() -> None: - # our model type can be assigned to Pydantic's model type - - def takes_pydantic(model: pydantic.BaseModel) -> None: # noqa: ARG001 - ... - - class OurModel(BaseModel): - foo: Optional[str] = None - - takes_pydantic(OurModel()) - - -def test_annotated_types() -> None: - class Model(BaseModel): - value: str - - m = construct_type( - value={"value": "foo"}, - type_=cast(Any, Annotated[Model, "random metadata"]), - ) - assert isinstance(m, Model) - assert m.value == "foo" - - -def test_discriminated_unions_invalid_data() -> None: - class A(BaseModel): - type: Literal["a"] - - data: str - - class B(BaseModel): - type: Literal["b"] - - data: int - - m = construct_type( - value={"type": "b", "data": "foo"}, - type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), - ) - assert isinstance(m, B) - assert m.type == "b" - assert m.data == "foo" # type: ignore[comparison-overlap] - - m = construct_type( - value={"type": "a", "data": 100}, - type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), - ) - assert isinstance(m, A) - assert m.type == "a" - if PYDANTIC_V1: - # pydantic v1 automatically converts inputs to strings - # if the expected type is a str - assert m.data == "100" - else: - assert m.data == 100 # type: ignore[comparison-overlap] - - -def test_discriminated_unions_unknown_variant() -> None: - class A(BaseModel): - type: Literal["a"] - - data: str - - class B(BaseModel): - type: Literal["b"] - - data: int - - m = construct_type( - value={"type": "c", "data": None, "new_thing": "bar"}, - type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), - ) - - # just chooses the first variant - assert isinstance(m, A) - assert m.type == "c" # type: ignore[comparison-overlap] - assert m.data == None # type: ignore[unreachable] - assert m.new_thing == "bar" - - -def test_discriminated_unions_invalid_data_nested_unions() -> None: - class A(BaseModel): - type: Literal["a"] - - data: str - - class B(BaseModel): - type: Literal["b"] - - data: int - - class C(BaseModel): - type: Literal["c"] - - data: bool - - m = construct_type( - value={"type": "b", "data": "foo"}, - type_=cast(Any, Annotated[Union[Union[A, B], C], PropertyInfo(discriminator="type")]), - ) - assert isinstance(m, B) - assert m.type == "b" - assert m.data == "foo" # type: ignore[comparison-overlap] - - m = construct_type( - value={"type": "c", "data": "foo"}, - type_=cast(Any, Annotated[Union[Union[A, B], C], PropertyInfo(discriminator="type")]), - ) - assert isinstance(m, C) - assert m.type == "c" - assert m.data == "foo" # type: ignore[comparison-overlap] - - -def test_discriminated_unions_with_aliases_invalid_data() -> None: - class A(BaseModel): - foo_type: Literal["a"] = Field(alias="type") - - data: str - - class B(BaseModel): - foo_type: Literal["b"] = Field(alias="type") - - data: int - - m = construct_type( - value={"type": "b", "data": "foo"}, - type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="foo_type")]), - ) - assert isinstance(m, B) - assert m.foo_type == "b" - assert m.data == "foo" # type: ignore[comparison-overlap] - - m = construct_type( - value={"type": "a", "data": 100}, - type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="foo_type")]), - ) - assert isinstance(m, A) - assert m.foo_type == "a" - if PYDANTIC_V1: - # pydantic v1 automatically converts inputs to strings - # if the expected type is a str - assert m.data == "100" - else: - assert m.data == 100 # type: ignore[comparison-overlap] - - -def test_discriminated_unions_overlapping_discriminators_invalid_data() -> None: - class A(BaseModel): - type: Literal["a"] - - data: bool - - class B(BaseModel): - type: Literal["a"] - - data: int - - m = construct_type( - value={"type": "a", "data": "foo"}, - type_=cast(Any, Annotated[Union[A, B], PropertyInfo(discriminator="type")]), - ) - assert isinstance(m, B) - assert m.type == "a" - assert m.data == "foo" # type: ignore[comparison-overlap] - - -def test_discriminated_unions_invalid_data_uses_cache() -> None: - class A(BaseModel): - type: Literal["a"] - - data: str - - class B(BaseModel): - type: Literal["b"] - - data: int - - UnionType = cast(Any, Union[A, B]) - - assert not DISCRIMINATOR_CACHE.get(UnionType) - - m = construct_type( - value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) - ) - assert isinstance(m, B) - assert m.type == "b" - assert m.data == "foo" # type: ignore[comparison-overlap] - - discriminator = DISCRIMINATOR_CACHE.get(UnionType) - assert discriminator is not None - - m = construct_type( - value={"type": "b", "data": "foo"}, type_=cast(Any, Annotated[UnionType, PropertyInfo(discriminator="type")]) - ) - assert isinstance(m, B) - assert m.type == "b" - assert m.data == "foo" # type: ignore[comparison-overlap] - - # if the discriminator details object stays the same between invocations then - # we hit the cache - assert DISCRIMINATOR_CACHE.get(UnionType) is discriminator - - -@pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") -def test_type_alias_type() -> None: - Alias = TypeAliasType("Alias", str) # pyright: ignore - - class Model(BaseModel): - alias: Alias - union: Union[int, Alias] - - m = construct_type(value={"alias": "foo", "union": "bar"}, type_=Model) - assert isinstance(m, Model) - assert isinstance(m.alias, str) - assert m.alias == "foo" - assert isinstance(m.union, str) - assert m.union == "bar" - - -@pytest.mark.skipif(PYDANTIC_V1, reason="TypeAliasType is not supported in Pydantic v1") -def test_field_named_cls() -> None: - class Model(BaseModel): - cls: str - - m = construct_type(value={"cls": "foo"}, type_=Model) - assert isinstance(m, Model) - assert isinstance(m.cls, str) - - -def test_discriminated_union_case() -> None: - class A(BaseModel): - type: Literal["a"] - - data: bool - - class B(BaseModel): - type: Literal["b"] - - data: List[Union[A, object]] - - class ModelA(BaseModel): - type: Literal["modelA"] - - data: int - - class ModelB(BaseModel): - type: Literal["modelB"] - - required: str - - data: Union[A, B] - - # when constructing ModelA | ModelB, value data doesn't match ModelB exactly - missing `required` - m = construct_type( - value={"type": "modelB", "data": {"type": "a", "data": True}}, - type_=cast(Any, Annotated[Union[ModelA, ModelB], PropertyInfo(discriminator="type")]), - ) - - assert isinstance(m, ModelB) - - -def test_nested_discriminated_union() -> None: - class InnerType1(BaseModel): - type: Literal["type_1"] - - class InnerModel(BaseModel): - inner_value: str - - class InnerType2(BaseModel): - type: Literal["type_2"] - some_inner_model: InnerModel - - class Type1(BaseModel): - base_type: Literal["base_type_1"] - value: Annotated[ - Union[ - InnerType1, - InnerType2, - ], - PropertyInfo(discriminator="type"), - ] - - class Type2(BaseModel): - base_type: Literal["base_type_2"] - - T = Annotated[ - Union[ - Type1, - Type2, - ], - PropertyInfo(discriminator="base_type"), - ] - - model = construct_type( - type_=T, - value={ - "base_type": "base_type_1", - "value": { - "type": "type_2", - }, - }, - ) - assert isinstance(model, Type1) - assert isinstance(model.value, InnerType2) - - -@pytest.mark.skipif(PYDANTIC_V1, reason="this is only supported in pydantic v2 for now") -def test_extra_properties() -> None: - class Item(BaseModel): - prop: int - - class Model(BaseModel): - __pydantic_extra__: Dict[str, Item] = Field(init=False) # pyright: ignore[reportIncompatibleVariableOverride] - - other: str - - if TYPE_CHECKING: - - def __getattr__(self, attr: str) -> Item: ... - - model = construct_type( - type_=Model, - value={ - "a": {"prop": 1}, - "other": "foo", - }, - ) - assert isinstance(model, Model) - 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"] diff --git a/tests/test_qs.py b/tests/test_qs.py deleted file mode 100644 index 3ca928c..0000000 --- a/tests/test_qs.py +++ /dev/null @@ -1,78 +0,0 @@ -from typing import Any, cast -from functools import partial -from urllib.parse import unquote - -import pytest - -from dedalus_sdk._qs import Querystring, stringify - - -def test_empty() -> None: - assert stringify({}) == "" - assert stringify({"a": {}}) == "" - assert stringify({"a": {"b": {"c": {}}}}) == "" - - -def test_basic() -> None: - assert stringify({"a": 1}) == "a=1" - assert stringify({"a": "b"}) == "a=b" - assert stringify({"a": True}) == "a=true" - assert stringify({"a": False}) == "a=false" - assert stringify({"a": 1.23456}) == "a=1.23456" - assert stringify({"a": None}) == "" - - -@pytest.mark.parametrize("method", ["class", "function"]) -def test_nested_dotted(method: str) -> None: - if method == "class": - serialise = Querystring(nested_format="dots").stringify - else: - serialise = partial(stringify, nested_format="dots") - - assert unquote(serialise({"a": {"b": "c"}})) == "a.b=c" - assert unquote(serialise({"a": {"b": "c", "d": "e", "f": "g"}})) == "a.b=c&a.d=e&a.f=g" - assert unquote(serialise({"a": {"b": {"c": {"d": "e"}}}})) == "a.b.c.d=e" - assert unquote(serialise({"a": {"b": True}})) == "a.b=true" - - -def test_nested_brackets() -> None: - assert unquote(stringify({"a": {"b": "c"}})) == "a[b]=c" - assert unquote(stringify({"a": {"b": "c", "d": "e", "f": "g"}})) == "a[b]=c&a[d]=e&a[f]=g" - assert unquote(stringify({"a": {"b": {"c": {"d": "e"}}}})) == "a[b][c][d]=e" - assert unquote(stringify({"a": {"b": True}})) == "a[b]=true" - - -@pytest.mark.parametrize("method", ["class", "function"]) -def test_array_comma(method: str) -> None: - if method == "class": - serialise = Querystring(array_format="comma").stringify - else: - serialise = partial(stringify, array_format="comma") - - assert unquote(serialise({"in": ["foo", "bar"]})) == "in=foo,bar" - assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b]=true,false" - assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b]=true,false,true" - - -def test_array_repeat() -> None: - assert unquote(stringify({"in": ["foo", "bar"]})) == "in=foo&in=bar" - assert unquote(stringify({"a": {"b": [True, False]}})) == "a[b]=true&a[b]=false" - assert unquote(stringify({"a": {"b": [True, False, None, True]}})) == "a[b]=true&a[b]=false&a[b]=true" - assert unquote(stringify({"in": ["foo", {"b": {"c": ["d", "e"]}}]})) == "in=foo&in[b][c]=d&in[b][c]=e" - - -@pytest.mark.parametrize("method", ["class", "function"]) -def test_array_brackets(method: str) -> None: - if method == "class": - serialise = Querystring(array_format="brackets").stringify - else: - serialise = partial(stringify, array_format="brackets") - - assert unquote(serialise({"in": ["foo", "bar"]})) == "in[]=foo&in[]=bar" - assert unquote(serialise({"a": {"b": [True, False]}})) == "a[b][]=true&a[b][]=false" - assert unquote(serialise({"a": {"b": [True, False, None, True]}})) == "a[b][]=true&a[b][]=false&a[b][]=true" - - -def test_unknown_array_format() -> None: - with pytest.raises(NotImplementedError, match="Unknown array_format value: foo, choose from comma, repeat"): - stringify({"a": ["foo", "bar"]}, array_format=cast(Any, "foo")) diff --git a/tests/test_required_args.py b/tests/test_required_args.py deleted file mode 100644 index d8a3f53..0000000 --- a/tests/test_required_args.py +++ /dev/null @@ -1,111 +0,0 @@ -from __future__ import annotations - -import pytest - -from dedalus_sdk._utils import required_args - - -def test_too_many_positional_params() -> None: - @required_args(["a"]) - def foo(a: str | None = None) -> str | None: - return a - - with pytest.raises(TypeError, match=r"foo\(\) takes 1 argument\(s\) but 2 were given"): - foo("a", "b") # type: ignore - - -def test_positional_param() -> None: - @required_args(["a"]) - def foo(a: str | None = None) -> str | None: - return a - - assert foo("a") == "a" - assert foo(None) is None - assert foo(a="b") == "b" - - with pytest.raises(TypeError, match="Missing required argument: 'a'"): - foo() - - -def test_keyword_only_param() -> None: - @required_args(["a"]) - def foo(*, a: str | None = None) -> str | None: - return a - - assert foo(a="a") == "a" - assert foo(a=None) is None - assert foo(a="b") == "b" - - with pytest.raises(TypeError, match="Missing required argument: 'a'"): - foo() - - -def test_multiple_params() -> None: - @required_args(["a", "b", "c"]) - def foo(a: str = "", *, b: str = "", c: str = "") -> str | None: - return f"{a} {b} {c}" - - assert foo(a="a", b="b", c="c") == "a b c" - - error_message = r"Missing required arguments.*" - - with pytest.raises(TypeError, match=error_message): - foo() - - with pytest.raises(TypeError, match=error_message): - foo(a="a") - - with pytest.raises(TypeError, match=error_message): - foo(b="b") - - with pytest.raises(TypeError, match=error_message): - foo(c="c") - - with pytest.raises(TypeError, match=r"Missing required argument: 'a'"): - foo(b="a", c="c") - - with pytest.raises(TypeError, match=r"Missing required argument: 'b'"): - foo("a", c="c") - - -def test_multiple_variants() -> None: - @required_args(["a"], ["b"]) - def foo(*, a: str | None = None, b: str | None = None) -> str | None: - return a if a is not None else b - - assert foo(a="foo") == "foo" - assert foo(b="bar") == "bar" - assert foo(a=None) is None - assert foo(b=None) is None - - # TODO: this error message could probably be improved - with pytest.raises( - TypeError, - match=r"Missing required arguments; Expected either \('a'\) or \('b'\) arguments to be given", - ): - foo() - - -def test_multiple_params_multiple_variants() -> None: - @required_args(["a", "b"], ["c"]) - def foo(*, a: str | None = None, b: str | None = None, c: str | None = None) -> str | None: - if a is not None: - return a - if b is not None: - return b - return c - - error_message = r"Missing required arguments; Expected either \('a' and 'b'\) or \('c'\) arguments to be given" - - with pytest.raises(TypeError, match=error_message): - foo(a="foo") - - with pytest.raises(TypeError, match=error_message): - foo(b="bar") - - with pytest.raises(TypeError, match=error_message): - foo() - - assert foo(a=None, b="bar") == "bar" - assert foo(c=None) is None - assert foo(c="foo") == "foo" diff --git a/tests/test_response.py b/tests/test_response.py deleted file mode 100644 index 790d212..0000000 --- a/tests/test_response.py +++ /dev/null @@ -1,277 +0,0 @@ -import json -from typing import Any, List, Union, cast -from typing_extensions import Annotated - -import httpx -import pytest -import pydantic - -from dedalus_sdk import Dedalus, BaseModel, AsyncDedalus -from dedalus_sdk._response import ( - APIResponse, - BaseAPIResponse, - AsyncAPIResponse, - BinaryAPIResponse, - AsyncBinaryAPIResponse, - extract_response_type, -) -from dedalus_sdk._streaming import Stream -from dedalus_sdk._base_client import FinalRequestOptions - - -class ConcreteBaseAPIResponse(APIResponse[bytes]): ... - - -class ConcreteAPIResponse(APIResponse[List[str]]): ... - - -class ConcreteAsyncAPIResponse(APIResponse[httpx.Response]): ... - - -def test_extract_response_type_direct_classes() -> None: - assert extract_response_type(BaseAPIResponse[str]) == str - assert extract_response_type(APIResponse[str]) == str - assert extract_response_type(AsyncAPIResponse[str]) == str - - -def test_extract_response_type_direct_class_missing_type_arg() -> None: - with pytest.raises( - RuntimeError, - match="Expected type to have a type argument at index 0 but it did not", - ): - extract_response_type(AsyncAPIResponse) - - -def test_extract_response_type_concrete_subclasses() -> None: - assert extract_response_type(ConcreteBaseAPIResponse) == bytes - assert extract_response_type(ConcreteAPIResponse) == List[str] - assert extract_response_type(ConcreteAsyncAPIResponse) == httpx.Response - - -def test_extract_response_type_binary_response() -> None: - assert extract_response_type(BinaryAPIResponse) == bytes - assert extract_response_type(AsyncBinaryAPIResponse) == bytes - - -class PydanticModel(pydantic.BaseModel): ... - - -def test_response_parse_mismatched_basemodel(client: Dedalus) -> None: - response = APIResponse( - raw=httpx.Response(200, content=b"foo"), - client=client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - with pytest.raises( - TypeError, - match="Pydantic models must subclass our base model type, e.g. `from dedalus_sdk import BaseModel`", - ): - response.parse(to=PydanticModel) - - -@pytest.mark.asyncio -async def test_async_response_parse_mismatched_basemodel(async_client: AsyncDedalus) -> None: - response = AsyncAPIResponse( - raw=httpx.Response(200, content=b"foo"), - client=async_client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - with pytest.raises( - TypeError, - match="Pydantic models must subclass our base model type, e.g. `from dedalus_sdk import BaseModel`", - ): - await response.parse(to=PydanticModel) - - -def test_response_parse_custom_stream(client: Dedalus) -> None: - response = APIResponse( - raw=httpx.Response(200, content=b"foo"), - client=client, - stream=True, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - stream = response.parse(to=Stream[int]) - assert stream._cast_to == int - - -@pytest.mark.asyncio -async def test_async_response_parse_custom_stream(async_client: AsyncDedalus) -> None: - response = AsyncAPIResponse( - raw=httpx.Response(200, content=b"foo"), - client=async_client, - stream=True, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - stream = await response.parse(to=Stream[int]) - assert stream._cast_to == int - - -class CustomModel(BaseModel): - foo: str - bar: int - - -def test_response_parse_custom_model(client: Dedalus) -> None: - response = APIResponse( - raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), - client=client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - obj = response.parse(to=CustomModel) - assert obj.foo == "hello!" - assert obj.bar == 2 - - -@pytest.mark.asyncio -async def test_async_response_parse_custom_model(async_client: AsyncDedalus) -> None: - response = AsyncAPIResponse( - raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), - client=async_client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - obj = await response.parse(to=CustomModel) - assert obj.foo == "hello!" - assert obj.bar == 2 - - -def test_response_parse_annotated_type(client: Dedalus) -> None: - response = APIResponse( - raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), - client=client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - obj = response.parse( - to=cast("type[CustomModel]", Annotated[CustomModel, "random metadata"]), - ) - assert obj.foo == "hello!" - assert obj.bar == 2 - - -async def test_async_response_parse_annotated_type(async_client: AsyncDedalus) -> None: - response = AsyncAPIResponse( - raw=httpx.Response(200, content=json.dumps({"foo": "hello!", "bar": 2})), - client=async_client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - obj = await response.parse( - to=cast("type[CustomModel]", Annotated[CustomModel, "random metadata"]), - ) - assert obj.foo == "hello!" - assert obj.bar == 2 - - -@pytest.mark.parametrize( - "content, expected", - [ - ("false", False), - ("true", True), - ("False", False), - ("True", True), - ("TrUe", True), - ("FalSe", False), - ], -) -def test_response_parse_bool(client: Dedalus, content: str, expected: bool) -> None: - response = APIResponse( - raw=httpx.Response(200, content=content), - client=client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - result = response.parse(to=bool) - assert result is expected - - -@pytest.mark.parametrize( - "content, expected", - [ - ("false", False), - ("true", True), - ("False", False), - ("True", True), - ("TrUe", True), - ("FalSe", False), - ], -) -async def test_async_response_parse_bool(client: AsyncDedalus, content: str, expected: bool) -> None: - response = AsyncAPIResponse( - raw=httpx.Response(200, content=content), - client=client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - result = await response.parse(to=bool) - assert result is expected - - -class OtherModel(BaseModel): - a: str - - -@pytest.mark.parametrize("client", [False], indirect=True) # loose validation -def test_response_parse_expect_model_union_non_json_content(client: Dedalus) -> None: - response = APIResponse( - raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), - client=client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - obj = response.parse(to=cast(Any, Union[CustomModel, OtherModel])) - assert isinstance(obj, str) - assert obj == "foo" - - -@pytest.mark.asyncio -@pytest.mark.parametrize("async_client", [False], indirect=True) # loose validation -async def test_async_response_parse_expect_model_union_non_json_content(async_client: AsyncDedalus) -> None: - response = AsyncAPIResponse( - raw=httpx.Response(200, content=b"foo", headers={"Content-Type": "application/text"}), - client=async_client, - stream=False, - stream_cls=None, - cast_to=str, - options=FinalRequestOptions.construct(method="get", url="/foo"), - ) - - obj = await response.parse(to=cast(Any, Union[CustomModel, OtherModel])) - assert isinstance(obj, str) - assert obj == "foo" diff --git a/tests/test_streaming.py b/tests/test_streaming.py deleted file mode 100644 index 4b29f43..0000000 --- a/tests/test_streaming.py +++ /dev/null @@ -1,248 +0,0 @@ -from __future__ import annotations - -from typing import Iterator, AsyncIterator - -import httpx -import pytest - -from dedalus_sdk import Dedalus, AsyncDedalus -from dedalus_sdk._streaming import Stream, AsyncStream, ServerSentEvent - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_basic(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b"event: completion\n" - yield b'data: {"foo":true}\n' - yield b"\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event == "completion" - assert sse.json() == {"foo": True} - - await assert_empty_iter(iterator) - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_missing_event(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b'data: {"foo":true}\n' - yield b"\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event is None - assert sse.json() == {"foo": True} - - await assert_empty_iter(iterator) - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_event_missing_data(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b"event: ping\n" - yield b"\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event == "ping" - assert sse.data == "" - - await assert_empty_iter(iterator) - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b"event: ping\n" - yield b"\n" - yield b"event: completion\n" - yield b"\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event == "ping" - assert sse.data == "" - - sse = await iter_next(iterator) - assert sse.event == "completion" - assert sse.data == "" - - await assert_empty_iter(iterator) - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_events_with_data(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b"event: ping\n" - yield b'data: {"foo":true}\n' - yield b"\n" - yield b"event: completion\n" - yield b'data: {"bar":false}\n' - yield b"\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event == "ping" - assert sse.json() == {"foo": True} - - sse = await iter_next(iterator) - assert sse.event == "completion" - assert sse.json() == {"bar": False} - - await assert_empty_iter(iterator) - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines_with_empty_line(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b"event: ping\n" - yield b"data: {\n" - yield b'data: "foo":\n' - yield b"data: \n" - yield b"data:\n" - yield b"data: true}\n" - yield b"\n\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event == "ping" - assert sse.json() == {"foo": True} - assert sse.data == '{\n"foo":\n\n\ntrue}' - - await assert_empty_iter(iterator) - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_data_json_escaped_double_new_line(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b"event: ping\n" - yield b'data: {"foo": "my long\\n\\ncontent"}' - yield b"\n\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event == "ping" - assert sse.json() == {"foo": "my long\n\ncontent"} - - await assert_empty_iter(iterator) - - -@pytest.mark.asyncio -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multiple_data_lines(sync: bool, client: Dedalus, async_client: AsyncDedalus) -> None: - def body() -> Iterator[bytes]: - yield b"event: ping\n" - yield b"data: {\n" - yield b'data: "foo":\n' - yield b"data: true}\n" - yield b"\n\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event == "ping" - assert sse.json() == {"foo": True} - - await assert_empty_iter(iterator) - - -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_special_new_line_character( - sync: bool, - client: Dedalus, - async_client: AsyncDedalus, -) -> None: - def body() -> Iterator[bytes]: - yield b'data: {"content":" culpa"}\n' - yield b"\n" - yield b'data: {"content":" \xe2\x80\xa8"}\n' - yield b"\n" - yield b'data: {"content":"foo"}\n' - yield b"\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event is None - assert sse.json() == {"content": " culpa"} - - sse = await iter_next(iterator) - assert sse.event is None - assert sse.json() == {"content": " 
"} - - sse = await iter_next(iterator) - assert sse.event is None - assert sse.json() == {"content": "foo"} - - await assert_empty_iter(iterator) - - -@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) -async def test_multi_byte_character_multiple_chunks( - sync: bool, - client: Dedalus, - async_client: AsyncDedalus, -) -> None: - def body() -> Iterator[bytes]: - yield b'data: {"content":"' - # bytes taken from the string 'известни' and arbitrarily split - # so that some multi-byte characters span multiple chunks - yield b"\xd0" - yield b"\xb8\xd0\xb7\xd0" - yield b"\xb2\xd0\xb5\xd1\x81\xd1\x82\xd0\xbd\xd0\xb8" - yield b'"}\n' - yield b"\n" - - iterator = make_event_iterator(content=body(), sync=sync, client=client, async_client=async_client) - - sse = await iter_next(iterator) - assert sse.event is None - assert sse.json() == {"content": "известни"} - - -async def to_aiter(iter: Iterator[bytes]) -> AsyncIterator[bytes]: - for chunk in iter: - yield chunk - - -async def iter_next(iter: Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]) -> ServerSentEvent: - if isinstance(iter, AsyncIterator): - return await iter.__anext__() - - return next(iter) - - -async def assert_empty_iter(iter: Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]) -> None: - with pytest.raises((StopAsyncIteration, RuntimeError)): - await iter_next(iter) - - -def make_event_iterator( - content: Iterator[bytes], - *, - sync: bool, - client: Dedalus, - async_client: AsyncDedalus, -) -> Iterator[ServerSentEvent] | AsyncIterator[ServerSentEvent]: - if sync: - return Stream(cast_to=object, client=client, response=httpx.Response(200, content=content))._iter_events() - - return AsyncStream( - cast_to=object, client=async_client, response=httpx.Response(200, content=to_aiter(content)) - )._iter_events() diff --git a/tests/test_transform.py b/tests/test_transform.py deleted file mode 100644 index dee2af7..0000000 --- a/tests/test_transform.py +++ /dev/null @@ -1,460 +0,0 @@ -from __future__ import annotations - -import io -import pathlib -from typing import Any, Dict, List, Union, TypeVar, Iterable, Optional, cast -from datetime import date, datetime -from typing_extensions import Required, Annotated, TypedDict - -import pytest - -from dedalus_sdk._types import Base64FileInput, omit, not_given -from dedalus_sdk._utils import ( - PropertyInfo, - transform as _transform, - parse_datetime, - async_transform as _async_transform, -) -from dedalus_sdk._compat import PYDANTIC_V1 -from dedalus_sdk._models import BaseModel - -_T = TypeVar("_T") - -SAMPLE_FILE_PATH = pathlib.Path(__file__).parent.joinpath("sample_file.txt") - - -async def transform( - data: _T, - expected_type: object, - use_async: bool, -) -> _T: - if use_async: - return await _async_transform(data, expected_type=expected_type) - - return _transform(data, expected_type=expected_type) - - -parametrize = pytest.mark.parametrize("use_async", [False, True], ids=["sync", "async"]) - - -class Foo1(TypedDict): - foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] - - -@parametrize -@pytest.mark.asyncio -async def test_top_level_alias(use_async: bool) -> None: - assert await transform({"foo_bar": "hello"}, expected_type=Foo1, use_async=use_async) == {"fooBar": "hello"} - - -class Foo2(TypedDict): - bar: Bar2 - - -class Bar2(TypedDict): - this_thing: Annotated[int, PropertyInfo(alias="this__thing")] - baz: Annotated[Baz2, PropertyInfo(alias="Baz")] - - -class Baz2(TypedDict): - my_baz: Annotated[str, PropertyInfo(alias="myBaz")] - - -@parametrize -@pytest.mark.asyncio -async def test_recursive_typeddict(use_async: bool) -> None: - assert await transform({"bar": {"this_thing": 1}}, Foo2, use_async) == {"bar": {"this__thing": 1}} - assert await transform({"bar": {"baz": {"my_baz": "foo"}}}, Foo2, use_async) == {"bar": {"Baz": {"myBaz": "foo"}}} - - -class Foo3(TypedDict): - things: List[Bar3] - - -class Bar3(TypedDict): - my_field: Annotated[str, PropertyInfo(alias="myField")] - - -@parametrize -@pytest.mark.asyncio -async def test_list_of_typeddict(use_async: bool) -> None: - result = await transform({"things": [{"my_field": "foo"}, {"my_field": "foo2"}]}, Foo3, use_async) - assert result == {"things": [{"myField": "foo"}, {"myField": "foo2"}]} - - -class Foo4(TypedDict): - foo: Union[Bar4, Baz4] - - -class Bar4(TypedDict): - foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] - - -class Baz4(TypedDict): - foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] - - -@parametrize -@pytest.mark.asyncio -async def test_union_of_typeddict(use_async: bool) -> None: - assert await transform({"foo": {"foo_bar": "bar"}}, Foo4, use_async) == {"foo": {"fooBar": "bar"}} - assert await transform({"foo": {"foo_baz": "baz"}}, Foo4, use_async) == {"foo": {"fooBaz": "baz"}} - assert await transform({"foo": {"foo_baz": "baz", "foo_bar": "bar"}}, Foo4, use_async) == { - "foo": {"fooBaz": "baz", "fooBar": "bar"} - } - - -class Foo5(TypedDict): - foo: Annotated[Union[Bar4, List[Baz4]], PropertyInfo(alias="FOO")] - - -class Bar5(TypedDict): - foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] - - -class Baz5(TypedDict): - foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] - - -@parametrize -@pytest.mark.asyncio -async def test_union_of_list(use_async: bool) -> None: - assert await transform({"foo": {"foo_bar": "bar"}}, Foo5, use_async) == {"FOO": {"fooBar": "bar"}} - assert await transform( - { - "foo": [ - {"foo_baz": "baz"}, - {"foo_baz": "baz"}, - ] - }, - Foo5, - use_async, - ) == {"FOO": [{"fooBaz": "baz"}, {"fooBaz": "baz"}]} - - -class Foo6(TypedDict): - bar: Annotated[str, PropertyInfo(alias="Bar")] - - -@parametrize -@pytest.mark.asyncio -async def test_includes_unknown_keys(use_async: bool) -> None: - assert await transform({"bar": "bar", "baz_": {"FOO": 1}}, Foo6, use_async) == { - "Bar": "bar", - "baz_": {"FOO": 1}, - } - - -class Foo7(TypedDict): - bar: Annotated[List[Bar7], PropertyInfo(alias="bAr")] - foo: Bar7 - - -class Bar7(TypedDict): - foo: str - - -@parametrize -@pytest.mark.asyncio -async def test_ignores_invalid_input(use_async: bool) -> None: - assert await transform({"bar": ""}, Foo7, use_async) == {"bAr": ""} - assert await transform({"foo": ""}, Foo7, use_async) == {"foo": ""} - - -class DatetimeDict(TypedDict, total=False): - foo: Annotated[datetime, PropertyInfo(format="iso8601")] - - bar: Annotated[Optional[datetime], PropertyInfo(format="iso8601")] - - required: Required[Annotated[Optional[datetime], PropertyInfo(format="iso8601")]] - - list_: Required[Annotated[Optional[List[datetime]], PropertyInfo(format="iso8601")]] - - union: Annotated[Union[int, datetime], PropertyInfo(format="iso8601")] - - -class DateDict(TypedDict, total=False): - foo: Annotated[date, PropertyInfo(format="iso8601")] - - -class DatetimeModel(BaseModel): - foo: datetime - - -class DateModel(BaseModel): - foo: Optional[date] - - -@parametrize -@pytest.mark.asyncio -async def test_iso8601_format(use_async: bool) -> None: - dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") - tz = "+00:00" if PYDANTIC_V1 else "Z" - assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] - assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692" + tz} # type: ignore[comparison-overlap] - - dt = dt.replace(tzinfo=None) - assert await transform({"foo": dt}, DatetimeDict, use_async) == {"foo": "2023-02-23T14:16:36.337692"} # type: ignore[comparison-overlap] - assert await transform(DatetimeModel(foo=dt), Any, use_async) == {"foo": "2023-02-23T14:16:36.337692"} # type: ignore[comparison-overlap] - - assert await transform({"foo": None}, DateDict, use_async) == {"foo": None} # type: ignore[comparison-overlap] - assert await transform(DateModel(foo=None), Any, use_async) == {"foo": None} # type: ignore - assert await transform({"foo": date.fromisoformat("2023-02-23")}, DateDict, use_async) == {"foo": "2023-02-23"} # type: ignore[comparison-overlap] - assert await transform(DateModel(foo=date.fromisoformat("2023-02-23")), DateDict, use_async) == { - "foo": "2023-02-23" - } # type: ignore[comparison-overlap] - - -@parametrize -@pytest.mark.asyncio -async def test_optional_iso8601_format(use_async: bool) -> None: - dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") - assert await transform({"bar": dt}, DatetimeDict, use_async) == {"bar": "2023-02-23T14:16:36.337692+00:00"} # type: ignore[comparison-overlap] - - assert await transform({"bar": None}, DatetimeDict, use_async) == {"bar": None} - - -@parametrize -@pytest.mark.asyncio -async def test_required_iso8601_format(use_async: bool) -> None: - dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") - assert await transform({"required": dt}, DatetimeDict, use_async) == { - "required": "2023-02-23T14:16:36.337692+00:00" - } # type: ignore[comparison-overlap] - - assert await transform({"required": None}, DatetimeDict, use_async) == {"required": None} - - -@parametrize -@pytest.mark.asyncio -async def test_union_datetime(use_async: bool) -> None: - dt = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") - assert await transform({"union": dt}, DatetimeDict, use_async) == { # type: ignore[comparison-overlap] - "union": "2023-02-23T14:16:36.337692+00:00" - } - - assert await transform({"union": "foo"}, DatetimeDict, use_async) == {"union": "foo"} - - -@parametrize -@pytest.mark.asyncio -async def test_nested_list_iso6801_format(use_async: bool) -> None: - dt1 = datetime.fromisoformat("2023-02-23T14:16:36.337692+00:00") - dt2 = parse_datetime("2022-01-15T06:34:23Z") - assert await transform({"list_": [dt1, dt2]}, DatetimeDict, use_async) == { # type: ignore[comparison-overlap] - "list_": ["2023-02-23T14:16:36.337692+00:00", "2022-01-15T06:34:23+00:00"] - } - - -@parametrize -@pytest.mark.asyncio -async def test_datetime_custom_format(use_async: bool) -> None: - dt = parse_datetime("2022-01-15T06:34:23Z") - - result = await transform(dt, Annotated[datetime, PropertyInfo(format="custom", format_template="%H")], use_async) - assert result == "06" # type: ignore[comparison-overlap] - - -class DateDictWithRequiredAlias(TypedDict, total=False): - required_prop: Required[Annotated[date, PropertyInfo(format="iso8601", alias="prop")]] - - -@parametrize -@pytest.mark.asyncio -async def test_datetime_with_alias(use_async: bool) -> None: - assert await transform({"required_prop": None}, DateDictWithRequiredAlias, use_async) == {"prop": None} # type: ignore[comparison-overlap] - assert await transform( - {"required_prop": date.fromisoformat("2023-02-23")}, DateDictWithRequiredAlias, use_async - ) == {"prop": "2023-02-23"} # type: ignore[comparison-overlap] - - -class MyModel(BaseModel): - foo: str - - -@parametrize -@pytest.mark.asyncio -async def test_pydantic_model_to_dictionary(use_async: bool) -> None: - assert cast(Any, await transform(MyModel(foo="hi!"), Any, use_async)) == {"foo": "hi!"} - assert cast(Any, await transform(MyModel.construct(foo="hi!"), Any, use_async)) == {"foo": "hi!"} - - -@parametrize -@pytest.mark.asyncio -async def test_pydantic_empty_model(use_async: bool) -> None: - assert cast(Any, await transform(MyModel.construct(), Any, use_async)) == {} - - -@parametrize -@pytest.mark.asyncio -async def test_pydantic_unknown_field(use_async: bool) -> None: - assert cast(Any, await transform(MyModel.construct(my_untyped_field=True), Any, use_async)) == { - "my_untyped_field": True - } - - -@parametrize -@pytest.mark.asyncio -async def test_pydantic_mismatched_types(use_async: bool) -> None: - model = MyModel.construct(foo=True) - if PYDANTIC_V1: - params = await transform(model, Any, use_async) - else: - with pytest.warns(UserWarning): - params = await transform(model, Any, use_async) - assert cast(Any, params) == {"foo": True} - - -@parametrize -@pytest.mark.asyncio -async def test_pydantic_mismatched_object_type(use_async: bool) -> None: - model = MyModel.construct(foo=MyModel.construct(hello="world")) - if PYDANTIC_V1: - params = await transform(model, Any, use_async) - else: - with pytest.warns(UserWarning): - params = await transform(model, Any, use_async) - assert cast(Any, params) == {"foo": {"hello": "world"}} - - -class ModelNestedObjects(BaseModel): - nested: MyModel - - -@parametrize -@pytest.mark.asyncio -async def test_pydantic_nested_objects(use_async: bool) -> None: - model = ModelNestedObjects.construct(nested={"foo": "stainless"}) - assert isinstance(model.nested, MyModel) - assert cast(Any, await transform(model, Any, use_async)) == {"nested": {"foo": "stainless"}} - - -class ModelWithDefaultField(BaseModel): - foo: str - with_none_default: Union[str, None] = None - with_str_default: str = "foo" - - -@parametrize -@pytest.mark.asyncio -async def test_pydantic_default_field(use_async: bool) -> None: - # should be excluded when defaults are used - model = ModelWithDefaultField.construct() - assert model.with_none_default is None - assert model.with_str_default == "foo" - assert cast(Any, await transform(model, Any, use_async)) == {} - - # should be included when the default value is explicitly given - model = ModelWithDefaultField.construct(with_none_default=None, with_str_default="foo") - assert model.with_none_default is None - assert model.with_str_default == "foo" - assert cast(Any, await transform(model, Any, use_async)) == {"with_none_default": None, "with_str_default": "foo"} - - # should be included when a non-default value is explicitly given - model = ModelWithDefaultField.construct(with_none_default="bar", with_str_default="baz") - assert model.with_none_default == "bar" - assert model.with_str_default == "baz" - assert cast(Any, await transform(model, Any, use_async)) == {"with_none_default": "bar", "with_str_default": "baz"} - - -class TypedDictIterableUnion(TypedDict): - foo: Annotated[Union[Bar8, Iterable[Baz8]], PropertyInfo(alias="FOO")] - - -class Bar8(TypedDict): - foo_bar: Annotated[str, PropertyInfo(alias="fooBar")] - - -class Baz8(TypedDict): - foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] - - -@parametrize -@pytest.mark.asyncio -async def test_iterable_of_dictionaries(use_async: bool) -> None: - assert await transform({"foo": [{"foo_baz": "bar"}]}, TypedDictIterableUnion, use_async) == { - "FOO": [{"fooBaz": "bar"}] - } - assert cast(Any, await transform({"foo": ({"foo_baz": "bar"},)}, TypedDictIterableUnion, use_async)) == { - "FOO": [{"fooBaz": "bar"}] - } - - def my_iter() -> Iterable[Baz8]: - yield {"foo_baz": "hello"} - yield {"foo_baz": "world"} - - assert await transform({"foo": my_iter()}, TypedDictIterableUnion, use_async) == { - "FOO": [{"fooBaz": "hello"}, {"fooBaz": "world"}] - } - - -@parametrize -@pytest.mark.asyncio -async def test_dictionary_items(use_async: bool) -> None: - class DictItems(TypedDict): - foo_baz: Annotated[str, PropertyInfo(alias="fooBaz")] - - assert await transform({"foo": {"foo_baz": "bar"}}, Dict[str, DictItems], use_async) == {"foo": {"fooBaz": "bar"}} - - -class TypedDictIterableUnionStr(TypedDict): - foo: Annotated[Union[str, Iterable[Baz8]], PropertyInfo(alias="FOO")] - - -@parametrize -@pytest.mark.asyncio -async def test_iterable_union_str(use_async: bool) -> None: - assert await transform({"foo": "bar"}, TypedDictIterableUnionStr, use_async) == {"FOO": "bar"} - assert cast(Any, await transform(iter([{"foo_baz": "bar"}]), Union[str, Iterable[Baz8]], use_async)) == [ - {"fooBaz": "bar"} - ] - - -class TypedDictBase64Input(TypedDict): - foo: Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")] - - -@parametrize -@pytest.mark.asyncio -async def test_base64_file_input(use_async: bool) -> None: - # strings are left as-is - assert await transform({"foo": "bar"}, TypedDictBase64Input, use_async) == {"foo": "bar"} - - # pathlib.Path is automatically converted to base64 - assert await transform({"foo": SAMPLE_FILE_PATH}, TypedDictBase64Input, use_async) == { - "foo": "SGVsbG8sIHdvcmxkIQo=" - } # type: ignore[comparison-overlap] - - # io instances are automatically converted to base64 - assert await transform({"foo": io.StringIO("Hello, world!")}, TypedDictBase64Input, use_async) == { - "foo": "SGVsbG8sIHdvcmxkIQ==" - } # type: ignore[comparison-overlap] - assert await transform({"foo": io.BytesIO(b"Hello, world!")}, TypedDictBase64Input, use_async) == { - "foo": "SGVsbG8sIHdvcmxkIQ==" - } # type: ignore[comparison-overlap] - - -@parametrize -@pytest.mark.asyncio -async def test_transform_skipping(use_async: bool) -> None: - # lists of ints are left as-is - data = [1, 2, 3] - assert await transform(data, List[int], use_async) is data - - # iterables of ints are converted to a list - data = iter([1, 2, 3]) - assert await transform(data, Iterable[int], use_async) == [1, 2, 3] - - -@parametrize -@pytest.mark.asyncio -async def test_strips_notgiven(use_async: bool) -> None: - assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} - assert await transform({"foo_bar": not_given}, Foo1, use_async) == {} - - -@parametrize -@pytest.mark.asyncio -async def test_strips_omit(use_async: bool) -> None: - assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} - assert await transform({"foo_bar": omit}, Foo1, use_async) == {} diff --git a/tests/test_utils/test_datetime_parse.py b/tests/test_utils/test_datetime_parse.py deleted file mode 100644 index e129974..0000000 --- a/tests/test_utils/test_datetime_parse.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -Copied from https://github.com/pydantic/pydantic/blob/v1.10.22/tests/test_datetime_parse.py -with modifications so it works without pydantic v1 imports. -""" - -from typing import Type, Union -from datetime import date, datetime, timezone, timedelta - -import pytest - -from dedalus_sdk._utils import parse_date, parse_datetime - - -def create_tz(minutes: int) -> timezone: - return timezone(timedelta(minutes=minutes)) - - -@pytest.mark.parametrize( - "value,result", - [ - # Valid inputs - ("1494012444.883309", date(2017, 5, 5)), - (b"1494012444.883309", date(2017, 5, 5)), - (1_494_012_444.883_309, date(2017, 5, 5)), - ("1494012444", date(2017, 5, 5)), - (1_494_012_444, date(2017, 5, 5)), - (0, date(1970, 1, 1)), - ("2012-04-23", date(2012, 4, 23)), - (b"2012-04-23", date(2012, 4, 23)), - ("2012-4-9", date(2012, 4, 9)), - (date(2012, 4, 9), date(2012, 4, 9)), - (datetime(2012, 4, 9, 12, 15), date(2012, 4, 9)), - # Invalid inputs - ("x20120423", ValueError), - ("2012-04-56", ValueError), - (19_999_999_999, date(2603, 10, 11)), # just before watershed - (20_000_000_001, date(1970, 8, 20)), # just after watershed - (1_549_316_052, date(2019, 2, 4)), # nowish in s - (1_549_316_052_104, date(2019, 2, 4)), # nowish in ms - (1_549_316_052_104_324, date(2019, 2, 4)), # nowish in μs - (1_549_316_052_104_324_096, date(2019, 2, 4)), # nowish in ns - ("infinity", date(9999, 12, 31)), - ("inf", date(9999, 12, 31)), - (float("inf"), date(9999, 12, 31)), - ("infinity ", date(9999, 12, 31)), - (int("1" + "0" * 100), date(9999, 12, 31)), - (1e1000, date(9999, 12, 31)), - ("-infinity", date(1, 1, 1)), - ("-inf", date(1, 1, 1)), - ("nan", ValueError), - ], -) -def test_date_parsing(value: Union[str, bytes, int, float], result: Union[date, Type[Exception]]) -> None: - if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] - with pytest.raises(result): - parse_date(value) - else: - assert parse_date(value) == result - - -@pytest.mark.parametrize( - "value,result", - [ - # Valid inputs - # values in seconds - ("1494012444.883309", datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), - (1_494_012_444.883_309, datetime(2017, 5, 5, 19, 27, 24, 883_309, tzinfo=timezone.utc)), - ("1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), - (b"1494012444", datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), - (1_494_012_444, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), - # values in ms - ("1494012444000.883309", datetime(2017, 5, 5, 19, 27, 24, 883, tzinfo=timezone.utc)), - ("-1494012444000.883309", datetime(1922, 8, 29, 4, 32, 35, 999117, tzinfo=timezone.utc)), - (1_494_012_444_000, datetime(2017, 5, 5, 19, 27, 24, tzinfo=timezone.utc)), - ("2012-04-23T09:15:00", datetime(2012, 4, 23, 9, 15)), - ("2012-4-9 4:8:16", datetime(2012, 4, 9, 4, 8, 16)), - ("2012-04-23T09:15:00Z", datetime(2012, 4, 23, 9, 15, 0, 0, timezone.utc)), - ("2012-4-9 4:8:16-0320", datetime(2012, 4, 9, 4, 8, 16, 0, create_tz(-200))), - ("2012-04-23T10:20:30.400+02:30", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(150))), - ("2012-04-23T10:20:30.400+02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(120))), - ("2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), - (b"2012-04-23T10:20:30.400-02", datetime(2012, 4, 23, 10, 20, 30, 400_000, create_tz(-120))), - (datetime(2017, 5, 5), datetime(2017, 5, 5)), - (0, datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc)), - # Invalid inputs - ("x20120423091500", ValueError), - ("2012-04-56T09:15:90", ValueError), - ("2012-04-23T11:05:00-25:00", ValueError), - (19_999_999_999, datetime(2603, 10, 11, 11, 33, 19, tzinfo=timezone.utc)), # just before watershed - (20_000_000_001, datetime(1970, 8, 20, 11, 33, 20, 1000, tzinfo=timezone.utc)), # just after watershed - (1_549_316_052, datetime(2019, 2, 4, 21, 34, 12, 0, tzinfo=timezone.utc)), # nowish in s - (1_549_316_052_104, datetime(2019, 2, 4, 21, 34, 12, 104_000, tzinfo=timezone.utc)), # nowish in ms - (1_549_316_052_104_324, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in μs - (1_549_316_052_104_324_096, datetime(2019, 2, 4, 21, 34, 12, 104_324, tzinfo=timezone.utc)), # nowish in ns - ("infinity", datetime(9999, 12, 31, 23, 59, 59, 999999)), - ("inf", datetime(9999, 12, 31, 23, 59, 59, 999999)), - ("inf ", datetime(9999, 12, 31, 23, 59, 59, 999999)), - (1e50, datetime(9999, 12, 31, 23, 59, 59, 999999)), - (float("inf"), datetime(9999, 12, 31, 23, 59, 59, 999999)), - ("-infinity", datetime(1, 1, 1, 0, 0)), - ("-inf", datetime(1, 1, 1, 0, 0)), - ("nan", ValueError), - ], -) -def test_datetime_parsing(value: Union[str, bytes, int, float], result: Union[datetime, Type[Exception]]) -> None: - if type(result) == type and issubclass(result, Exception): # pyright: ignore[reportUnnecessaryIsInstance] - with pytest.raises(result): - parse_datetime(value) - else: - assert parse_datetime(value) == result diff --git a/tests/test_utils/test_json.py b/tests/test_utils/test_json.py deleted file mode 100644 index 246547d..0000000 --- a/tests/test_utils/test_json.py +++ /dev/null @@ -1,126 +0,0 @@ -from __future__ import annotations - -import datetime -from typing import Union - -import pydantic - -from dedalus_sdk import _compat -from dedalus_sdk._utils._json import openapi_dumps - - -class TestOpenapiDumps: - def test_basic(self) -> None: - data = {"key": "value", "number": 42} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"key":"value","number":42}' - - def test_datetime_serialization(self) -> None: - dt = datetime.datetime(2023, 1, 1, 12, 0, 0) - data = {"datetime": dt} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"datetime":"2023-01-01T12:00:00"}' - - def test_pydantic_model_serialization(self) -> None: - class User(pydantic.BaseModel): - first_name: str - last_name: str - age: int - - model_instance = User(first_name="John", last_name="Kramer", age=83) - data = {"model": model_instance} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"first_name":"John","last_name":"Kramer","age":83}}' - - def test_pydantic_model_with_default_values(self) -> None: - class User(pydantic.BaseModel): - name: str - role: str = "user" - active: bool = True - score: int = 0 - - model_instance = User(name="Alice") - data = {"model": model_instance} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"name":"Alice"}}' - - def test_pydantic_model_with_default_values_overridden(self) -> None: - class User(pydantic.BaseModel): - name: str - role: str = "user" - active: bool = True - - model_instance = User(name="Bob", role="admin", active=False) - data = {"model": model_instance} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"name":"Bob","role":"admin","active":false}}' - - def test_pydantic_model_with_alias(self) -> None: - class User(pydantic.BaseModel): - first_name: str = pydantic.Field(alias="firstName") - last_name: str = pydantic.Field(alias="lastName") - - model_instance = User(firstName="John", lastName="Doe") - data = {"model": model_instance} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"firstName":"John","lastName":"Doe"}}' - - def test_pydantic_model_with_alias_and_default(self) -> None: - class User(pydantic.BaseModel): - user_name: str = pydantic.Field(alias="userName") - user_role: str = pydantic.Field(default="member", alias="userRole") - is_active: bool = pydantic.Field(default=True, alias="isActive") - - model_instance = User(userName="charlie") - data = {"model": model_instance} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"userName":"charlie"}}' - - model_with_overrides = User(userName="diana", userRole="admin", isActive=False) - data = {"model": model_with_overrides} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"userName":"diana","userRole":"admin","isActive":false}}' - - def test_pydantic_model_with_nested_models_and_defaults(self) -> None: - class Address(pydantic.BaseModel): - street: str - city: str = "Unknown" - - class User(pydantic.BaseModel): - name: str - address: Address - verified: bool = False - - if _compat.PYDANTIC_V1: - # to handle forward references in Pydantic v1 - User.update_forward_refs(**locals()) # type: ignore[reportDeprecated] - - address = Address(street="123 Main St") - user = User(name="Diana", address=address) - data = {"user": user} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"user":{"name":"Diana","address":{"street":"123 Main St"}}}' - - address_with_city = Address(street="456 Oak Ave", city="Boston") - user_verified = User(name="Eve", address=address_with_city, verified=True) - data = {"user": user_verified} - json_bytes = openapi_dumps(data) - assert ( - json_bytes == b'{"user":{"name":"Eve","address":{"street":"456 Oak Ave","city":"Boston"},"verified":true}}' - ) - - def test_pydantic_model_with_optional_fields(self) -> None: - class User(pydantic.BaseModel): - name: str - email: Union[str, None] - phone: Union[str, None] - - model_with_none = User(name="Eve", email=None, phone=None) - data = {"model": model_with_none} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"name":"Eve","email":null,"phone":null}}' - - model_with_values = User(name="Frank", email="frank@example.com", phone=None) - data = {"model": model_with_values} - json_bytes = openapi_dumps(data) - assert json_bytes == b'{"model":{"name":"Frank","email":"frank@example.com","phone":null}}' diff --git a/tests/test_utils/test_path.py b/tests/test_utils/test_path.py deleted file mode 100644 index 9f0b3e8..0000000 --- a/tests/test_utils/test_path.py +++ /dev/null @@ -1,89 +0,0 @@ -from __future__ import annotations - -from typing import Any - -import pytest - -from dedalus_sdk._utils._path import path_template - - -@pytest.mark.parametrize( - "template, kwargs, expected", - [ - ("/v1/{id}", dict(id="abc"), "/v1/abc"), - ("/v1/{a}/{b}", dict(a="x", b="y"), "/v1/x/y"), - ("/v1/{a}{b}/path/{c}?val={d}#{e}", dict(a="x", b="y", c="z", d="u", e="v"), "/v1/xy/path/z?val=u#v"), - ("/{w}/{w}", dict(w="echo"), "/echo/echo"), - ("/v1/static", {}, "/v1/static"), - ("", {}, ""), - ("/v1/?q={n}&count=10", dict(n=42), "/v1/?q=42&count=10"), - ("/v1/{v}", dict(v=None), "/v1/null"), - ("/v1/{v}", dict(v=True), "/v1/true"), - ("/v1/{v}", dict(v=False), "/v1/false"), - ("/v1/{v}", dict(v=".hidden"), "/v1/.hidden"), # dot prefix ok - ("/v1/{v}", dict(v="file.txt"), "/v1/file.txt"), # dot in middle ok - ("/v1/{v}", dict(v="..."), "/v1/..."), # triple dot ok - ("/v1/{a}{b}", dict(a=".", b="txt"), "/v1/.txt"), # dot var combining with adjacent to be ok - ("/items?q={v}#{f}", dict(v=".", f=".."), "/items?q=.#.."), # dots in query/fragment are fine - ( - "/v1/{a}?query={b}", - dict(a="../../other/endpoint", b="a&bad=true"), - "/v1/..%2F..%2Fother%2Fendpoint?query=a%26bad%3Dtrue", - ), - ("/v1/{val}", dict(val="a/b/c"), "/v1/a%2Fb%2Fc"), - ("/v1/{val}", dict(val="a/b/c?query=value"), "/v1/a%2Fb%2Fc%3Fquery=value"), - ("/v1/{val}", dict(val="a/b/c?query=value&bad=true"), "/v1/a%2Fb%2Fc%3Fquery=value&bad=true"), - ("/v1/{val}", dict(val="%20"), "/v1/%2520"), # escapes escape sequences in input - # Query: slash and ? are safe, # is not - ("/items?q={v}", dict(v="a/b"), "/items?q=a/b"), - ("/items?q={v}", dict(v="a?b"), "/items?q=a?b"), - ("/items?q={v}", dict(v="a#b"), "/items?q=a%23b"), - ("/items?q={v}", dict(v="a b"), "/items?q=a%20b"), - # Fragment: slash and ? are safe - ("/docs#{v}", dict(v="a/b"), "/docs#a/b"), - ("/docs#{v}", dict(v="a?b"), "/docs#a?b"), - # Path: slash, ? and # are all encoded - ("/v1/{v}", dict(v="a/b"), "/v1/a%2Fb"), - ("/v1/{v}", dict(v="a?b"), "/v1/a%3Fb"), - ("/v1/{v}", dict(v="a#b"), "/v1/a%23b"), - # same var encoded differently by component - ( - "/v1/{v}?q={v}#{v}", - dict(v="a/b?c#d"), - "/v1/a%2Fb%3Fc%23d?q=a/b?c%23d#a/b?c%23d", - ), - ("/v1/{val}", dict(val="x?admin=true"), "/v1/x%3Fadmin=true"), # query injection - ("/v1/{val}", dict(val="x#admin"), "/v1/x%23admin"), # fragment injection - ], -) -def test_interpolation(template: str, kwargs: dict[str, Any], expected: str) -> None: - assert path_template(template, **kwargs) == expected - - -def test_missing_kwarg_raises_key_error() -> None: - with pytest.raises(KeyError, match="org_id"): - path_template("/v1/{org_id}") - - -@pytest.mark.parametrize( - "template, kwargs", - [ - ("{a}/path", dict(a=".")), - ("{a}/path", dict(a="..")), - ("/v1/{a}", dict(a=".")), - ("/v1/{a}", dict(a="..")), - ("/v1/{a}/path", dict(a=".")), - ("/v1/{a}/path", dict(a="..")), - ("/v1/{a}{b}", dict(a=".", b=".")), # adjacent vars → ".." - ("/v1/{a}.", dict(a=".")), # var + static → ".." - ("/v1/{a}{b}", dict(a="", b=".")), # empty + dot → "." - ("/v1/%2e/{x}", dict(x="ok")), # encoded dot in static text - ("/v1/%2e./{x}", dict(x="ok")), # mixed encoded ".." in static - ("/v1/.%2E/{x}", dict(x="ok")), # mixed encoded ".." in static - ("/v1/{v}?q=1", dict(v="..")), - ("/v1/{v}#frag", dict(v="..")), - ], -) -def test_dot_segment_rejected(template: str, kwargs: dict[str, Any]) -> None: - with pytest.raises(ValueError, match="dot-segment"): - path_template(template, **kwargs) diff --git a/tests/test_utils/test_proxy.py b/tests/test_utils/test_proxy.py deleted file mode 100644 index 935fd89..0000000 --- a/tests/test_utils/test_proxy.py +++ /dev/null @@ -1,34 +0,0 @@ -import operator -from typing import Any -from typing_extensions import override - -from dedalus_sdk._utils import LazyProxy - - -class RecursiveLazyProxy(LazyProxy[Any]): - @override - def __load__(self) -> Any: - return self - - def __call__(self, *_args: Any, **_kwds: Any) -> Any: - raise RuntimeError("This should never be called!") - - -def test_recursive_proxy() -> None: - proxy = RecursiveLazyProxy() - assert repr(proxy) == "RecursiveLazyProxy" - assert str(proxy) == "RecursiveLazyProxy" - assert dir(proxy) == [] - assert type(proxy).__name__ == "RecursiveLazyProxy" - assert type(operator.attrgetter("name.foo.bar.baz")(proxy)).__name__ == "RecursiveLazyProxy" - - -def test_isinstance_does_not_error() -> None: - class AlwaysErrorProxy(LazyProxy[Any]): - @override - def __load__(self) -> Any: - raise RuntimeError("Mocking missing dependency") - - proxy = AlwaysErrorProxy() - assert not isinstance(proxy, dict) - assert isinstance(proxy, LazyProxy) diff --git a/tests/test_utils/test_typing.py b/tests/test_utils/test_typing.py deleted file mode 100644 index ef8c14e..0000000 --- a/tests/test_utils/test_typing.py +++ /dev/null @@ -1,73 +0,0 @@ -from __future__ import annotations - -from typing import Generic, TypeVar, cast - -from dedalus_sdk._utils import extract_type_var_from_base - -_T = TypeVar("_T") -_T2 = TypeVar("_T2") -_T3 = TypeVar("_T3") - - -class BaseGeneric(Generic[_T]): ... - - -class SubclassGeneric(BaseGeneric[_T]): ... - - -class BaseGenericMultipleTypeArgs(Generic[_T, _T2, _T3]): ... - - -class SubclassGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T, _T2, _T3]): ... - - -class SubclassDifferentOrderGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T2, _T, _T3]): ... - - -def test_extract_type_var() -> None: - assert ( - extract_type_var_from_base( - BaseGeneric[int], - index=0, - generic_bases=cast("tuple[type, ...]", (BaseGeneric,)), - ) - == int - ) - - -def test_extract_type_var_generic_subclass() -> None: - assert ( - extract_type_var_from_base( - SubclassGeneric[int], - index=0, - generic_bases=cast("tuple[type, ...]", (BaseGeneric,)), - ) - == int - ) - - -def test_extract_type_var_multiple() -> None: - typ = BaseGenericMultipleTypeArgs[int, str, None] - - generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) - assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int - assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str - assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) - - -def test_extract_type_var_generic_subclass_multiple() -> None: - typ = SubclassGenericMultipleTypeArgs[int, str, None] - - generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) - assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int - assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str - assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) - - -def test_extract_type_var_generic_subclass_different_ordering_multiple() -> None: - typ = SubclassDifferentOrderGenericMultipleTypeArgs[int, str, None] - - generic_bases = cast("tuple[type, ...]", (BaseGenericMultipleTypeArgs,)) - assert extract_type_var_from_base(typ, index=0, generic_bases=generic_bases) == int - assert extract_type_var_from_base(typ, index=1, generic_bases=generic_bases) == str - assert extract_type_var_from_base(typ, index=2, generic_bases=generic_bases) == type(None) diff --git a/tests/utils.py b/tests/utils.py deleted file mode 100644 index 09df165..0000000 --- a/tests/utils.py +++ /dev/null @@ -1,167 +0,0 @@ -from __future__ import annotations - -import os -import inspect -import traceback -import contextlib -from typing import Any, TypeVar, Iterator, Sequence, cast -from datetime import date, datetime -from typing_extensions import Literal, get_args, get_origin, assert_type - -from dedalus_sdk._types import Omit, NoneType -from dedalus_sdk._utils import ( - is_dict, - is_list, - is_list_type, - is_union_type, - extract_type_arg, - is_sequence_type, - is_annotated_type, - is_type_alias_type, -) -from dedalus_sdk._compat import PYDANTIC_V1, field_outer_type, get_model_fields -from dedalus_sdk._models import BaseModel - -BaseModelT = TypeVar("BaseModelT", bound=BaseModel) - - -def assert_matches_model(model: type[BaseModelT], value: BaseModelT, *, path: list[str]) -> bool: - for name, field in get_model_fields(model).items(): - field_value = getattr(value, name) - if PYDANTIC_V1: - # in v1 nullability was structured differently - # https://docs.pydantic.dev/2.0/migration/#required-optional-and-nullable-fields - allow_none = getattr(field, "allow_none", False) - else: - allow_none = False - - assert_matches_type( - field_outer_type(field), - field_value, - path=[*path, name], - allow_none=allow_none, - ) - - return True - - -# Note: the `path` argument is only used to improve error messages when `--showlocals` is used -def assert_matches_type( - type_: Any, - value: object, - *, - path: list[str], - allow_none: bool = False, -) -> None: - if is_type_alias_type(type_): - type_ = type_.__value__ - - # unwrap `Annotated[T, ...]` -> `T` - if is_annotated_type(type_): - type_ = extract_type_arg(type_, 0) - - if allow_none and value is None: - return - - if type_ is None or type_ is NoneType: - assert value is None - return - - origin = get_origin(type_) or type_ - - if is_list_type(type_): - return _assert_list_type(type_, value) - - if is_sequence_type(type_): - assert isinstance(value, Sequence) - inner_type = get_args(type_)[0] - for entry in value: # type: ignore - assert_type(inner_type, entry) # type: ignore - return - - if origin == str: - assert isinstance(value, str) - elif origin == int: - assert isinstance(value, int) - elif origin == bool: - assert isinstance(value, bool) - elif origin == float: - assert isinstance(value, float) - elif origin == bytes: - assert isinstance(value, bytes) - elif origin == datetime: - assert isinstance(value, datetime) - elif origin == date: - assert isinstance(value, date) - elif origin == object: - # nothing to do here, the expected type is unknown - pass - elif origin == Literal: - assert value in get_args(type_) - elif origin == dict: - assert is_dict(value) - - args = get_args(type_) - key_type = args[0] - items_type = args[1] - - for key, item in value.items(): - assert_matches_type(key_type, key, path=[*path, ""]) - assert_matches_type(items_type, item, path=[*path, ""]) - elif is_union_type(type_): - variants = get_args(type_) - - try: - none_index = variants.index(type(None)) - except ValueError: - pass - else: - # special case Optional[T] for better error messages - if len(variants) == 2: - if value is None: - # valid - return - - return assert_matches_type(type_=variants[not none_index], value=value, path=path) - - for i, variant in enumerate(variants): - try: - assert_matches_type(variant, value, path=[*path, f"variant {i}"]) - return - except AssertionError: - traceback.print_exc() - continue - - raise AssertionError("Did not match any variants") - elif issubclass(origin, BaseModel): - assert isinstance(value, type_) - assert assert_matches_model(type_, cast(Any, value), path=path) - elif inspect.isclass(origin) and origin.__name__ == "HttpxBinaryResponseContent": - assert value.__class__.__name__ == "HttpxBinaryResponseContent" - else: - assert None, f"Unhandled field type: {type_}" - - -def _assert_list_type(type_: type[object], value: object) -> None: - assert is_list(value) - - inner_type = get_args(type_)[0] - for entry in value: - assert_type(inner_type, entry) # type: ignore - - -@contextlib.contextmanager -def update_env(**new_env: str | Omit) -> Iterator[None]: - old = os.environ.copy() - - try: - for name, value in new_env.items(): - if isinstance(value, Omit): - os.environ.pop(name, None) - else: - os.environ[name] = value - - yield None - finally: - os.environ.clear() - os.environ.update(old) diff --git a/uv.lock b/uv.lock deleted file mode 100644 index 2facb36..0000000 --- a/uv.lock +++ /dev/null @@ -1,1829 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.9" -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version < '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version < '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version < '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", -] -conflicts = [[ - { package = "dedalus-sdk", group = "pydantic-v1" }, - { package = "dedalus-sdk", group = "pydantic-v2" }, -]] - -[[package]] -name = "aiohappyeyeballs" -version = "2.6.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, -] - -[[package]] -name = "aiohttp" -version = "3.13.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohappyeyeballs" }, - { name = "aiosignal" }, - { name = "async-timeout", marker = "python_full_version < '3.11' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "attrs" }, - { name = "frozenlist" }, - { name = "multidict" }, - { name = "propcache" }, - { name = "yarl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/d6/5aec9313ee6ea9c7cde8b891b69f4ff4001416867104580670a31daeba5b/aiohttp-3.13.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7", size = 738950, upload-time = "2026-01-03T17:29:13.002Z" }, - { url = "https://files.pythonhosted.org/packages/68/03/8fa90a7e6d11ff20a18837a8e2b5dd23db01aabc475aa9271c8ad33299f5/aiohttp-3.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821", size = 496099, upload-time = "2026-01-03T17:29:15.268Z" }, - { url = "https://files.pythonhosted.org/packages/d2/23/b81f744d402510a8366b74eb420fc0cc1170d0c43daca12d10814df85f10/aiohttp-3.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845", size = 491072, upload-time = "2026-01-03T17:29:16.922Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e1/56d1d1c0dd334cd203dd97706ce004c1aa24b34a813b0b8daf3383039706/aiohttp-3.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af", size = 1671588, upload-time = "2026-01-03T17:29:18.539Z" }, - { url = "https://files.pythonhosted.org/packages/5f/34/8d7f962604f4bc2b4e39eb1220dac7d4e4cba91fb9ba0474b4ecd67db165/aiohttp-3.13.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940", size = 1640334, upload-time = "2026-01-03T17:29:21.028Z" }, - { url = "https://files.pythonhosted.org/packages/94/1d/fcccf2c668d87337ddeef9881537baee13c58d8f01f12ba8a24215f2b804/aiohttp-3.13.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160", size = 1722656, upload-time = "2026-01-03T17:29:22.531Z" }, - { url = "https://files.pythonhosted.org/packages/aa/98/c6f3b081c4c606bc1e5f2ec102e87d6411c73a9ef3616fea6f2d5c98c062/aiohttp-3.13.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7", size = 1817625, upload-time = "2026-01-03T17:29:24.276Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c0/cfcc3d2e11b477f86e1af2863f3858c8850d751ce8dc39c4058a072c9e54/aiohttp-3.13.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455", size = 1672604, upload-time = "2026-01-03T17:29:26.099Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/6b4ffcbcac4c6a5d041343a756f34a6dd26174ae07f977a64fe028dda5b0/aiohttp-3.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279", size = 1554370, upload-time = "2026-01-03T17:29:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f0/e3ddfa93f17d689dbe014ba048f18e0c9f9b456033b70e94349a2e9048be/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e", size = 1642023, upload-time = "2026-01-03T17:29:30.002Z" }, - { url = "https://files.pythonhosted.org/packages/eb/45/c14019c9ec60a8e243d06d601b33dcc4fd92379424bde3021725859d7f99/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d", size = 1649680, upload-time = "2026-01-03T17:29:31.782Z" }, - { url = "https://files.pythonhosted.org/packages/9c/fd/09c9451dae5aa5c5ed756df95ff9ef549d45d4be663bafd1e4954fd836f0/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808", size = 1692407, upload-time = "2026-01-03T17:29:33.392Z" }, - { url = "https://files.pythonhosted.org/packages/a6/81/938bc2ec33c10efd6637ccb3d22f9f3160d08e8f3aa2587a2c2d5ab578eb/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40", size = 1543047, upload-time = "2026-01-03T17:29:34.855Z" }, - { url = "https://files.pythonhosted.org/packages/f7/23/80488ee21c8d567c83045e412e1d9b7077d27171591a4eb7822586e8c06a/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29", size = 1715264, upload-time = "2026-01-03T17:29:36.389Z" }, - { url = "https://files.pythonhosted.org/packages/e2/83/259a8da6683182768200b368120ab3deff5370bed93880fb9a3a86299f34/aiohttp-3.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11", size = 1657275, upload-time = "2026-01-03T17:29:38.162Z" }, - { url = "https://files.pythonhosted.org/packages/3f/4f/2c41f800a0b560785c10fb316216ac058c105f9be50bdc6a285de88db625/aiohttp-3.13.3-cp310-cp310-win32.whl", hash = "sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd", size = 434053, upload-time = "2026-01-03T17:29:40.074Z" }, - { url = "https://files.pythonhosted.org/packages/80/df/29cd63c7ecfdb65ccc12f7d808cac4fa2a19544660c06c61a4a48462de0c/aiohttp-3.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c", size = 456687, upload-time = "2026-01-03T17:29:41.819Z" }, - { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, - { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, - { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, - { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, - { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, - { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, - { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, - { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, - { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, - { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, - { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, - { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, - { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, - { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, - { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, - { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, - { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, - { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, - { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, - { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, - { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, - { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, - { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, - { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, - { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, - { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, - { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, - { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, - { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, - { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, - { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, - { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, - { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, - { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, - { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, - { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, - { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, - { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, - { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, - { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, - { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, - { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, - { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, - { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, - { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, - { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, - { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, - { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, - { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, - { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, - { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, - { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, - { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, - { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, - { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, - { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, - { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, - { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, - { url = "https://files.pythonhosted.org/packages/bf/79/446655656861d3e7e2c32bfcf160c7aa9e9dc63776a691b124dba65cdd77/aiohttp-3.13.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e", size = 741433, upload-time = "2026-01-03T17:32:26.453Z" }, - { url = "https://files.pythonhosted.org/packages/cb/49/773c4b310b5140d2fb5e79bb0bf40b7b41dad80a288ca1a8759f5f72bda9/aiohttp-3.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7", size = 497332, upload-time = "2026-01-03T17:32:28.37Z" }, - { url = "https://files.pythonhosted.org/packages/bc/31/1dcbc4b83a4e6f76a0ad883f07f21ffbfe29750c89db97381701508c9f45/aiohttp-3.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02", size = 492365, upload-time = "2026-01-03T17:32:30.234Z" }, - { url = "https://files.pythonhosted.org/packages/5a/b5/b50657496c8754482cd7964e50aaf3aa84b3db61ed45daec4c1aec5b94b4/aiohttp-3.13.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43", size = 1660440, upload-time = "2026-01-03T17:32:32.586Z" }, - { url = "https://files.pythonhosted.org/packages/2a/73/9b69e5139d89d75127569298931444ad78ea86a5befd5599780b1e9a6880/aiohttp-3.13.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6", size = 1632740, upload-time = "2026-01-03T17:32:34.793Z" }, - { url = "https://files.pythonhosted.org/packages/ef/fe/3ea9b5af694b4e3aec0d0613a806132ca744747146fca68e96bf056f61a7/aiohttp-3.13.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce", size = 1719782, upload-time = "2026-01-03T17:32:37.737Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c2/46b3b06e60851cbb71efb0f79a3267279cbef7b12c58e68a1e897f269cca/aiohttp-3.13.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80", size = 1813527, upload-time = "2026-01-03T17:32:39.973Z" }, - { url = "https://files.pythonhosted.org/packages/36/23/71ceb78c769ed65fe4c697692de232b63dab399210678d2b00961ccb0619/aiohttp-3.13.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a", size = 1661268, upload-time = "2026-01-03T17:32:42.082Z" }, - { url = "https://files.pythonhosted.org/packages/c4/8d/86e929523d955e85ebab7c0e2b9e0cb63604cfc27dc3280e10d0063cf682/aiohttp-3.13.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6", size = 1552742, upload-time = "2026-01-03T17:32:44.622Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ea/3f5987cba1bab6bd151f0d97aa60f0ce04d3c83316692a6bb6ba2fb69f92/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558", size = 1632918, upload-time = "2026-01-03T17:32:46.749Z" }, - { url = "https://files.pythonhosted.org/packages/be/2c/7e1e85121f2e31ee938cb83a8f32dfafd4908530c10fabd6d46761c12ac7/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7", size = 1644446, upload-time = "2026-01-03T17:32:49.063Z" }, - { url = "https://files.pythonhosted.org/packages/5d/35/ce6133d423ad0e8ca976a7c848f7146bca3520eea4ccf6b95e2d077c9d20/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877", size = 1689487, upload-time = "2026-01-03T17:32:51.113Z" }, - { url = "https://files.pythonhosted.org/packages/50/f7/ff7a27c15603d460fd1366b3c22054f7ae4fa9310aca40b43bde35867fcd/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3", size = 1540715, upload-time = "2026-01-03T17:32:53.38Z" }, - { url = "https://files.pythonhosted.org/packages/17/02/053f11346e5b962e6d8a1c4f8c70c29d5970a1b4b8e7894c68e12c27a57f/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704", size = 1711835, upload-time = "2026-01-03T17:32:56.088Z" }, - { url = "https://files.pythonhosted.org/packages/fb/71/9b9761ddf276fd6708d13720197cbac19b8d67ecfa9116777924056cfcaa/aiohttp-3.13.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f", size = 1649593, upload-time = "2026-01-03T17:32:58.181Z" }, - { url = "https://files.pythonhosted.org/packages/ae/72/5d817e9ea218acae12a5e3b9ad1178cf0c12fc3570c0b47eea2daf95f9ea/aiohttp-3.13.3-cp39-cp39-win32.whl", hash = "sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1", size = 434831, upload-time = "2026-01-03T17:33:00.577Z" }, - { url = "https://files.pythonhosted.org/packages/39/cb/22659d9bf3149b7a2927bc2769cc9c8f8f5a80eba098398e03c199a43a85/aiohttp-3.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538", size = 457697, upload-time = "2026-01-03T17:33:03.167Z" }, -] - -[[package]] -name = "aiosignal" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, -] - -[[package]] -name = "annotated-types" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, -] - -[[package]] -name = "anyio" -version = "4.12.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "idna" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, -] - -[[package]] -name = "async-timeout" -version = "5.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, -] - -[[package]] -name = "attrs" -version = "25.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, -] - -[[package]] -name = "backports-asyncio-runner" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162", size = 69893, upload-time = "2025-07-02T02:27:15.685Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313, upload-time = "2025-07-02T02:27:14.263Z" }, -] - -[[package]] -name = "certifi" -version = "2026.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, -] - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, -] - -[[package]] -name = "dedalus-sdk" -version = "0.2.0" -source = { editable = "." } -dependencies = [ - { name = "anyio" }, - { name = "distro" }, - { name = "httpx" }, - { name = "pydantic", version = "1.10.26", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-11-dedalus-sdk-pydantic-v1'" }, - { name = "pydantic", version = "2.12.5", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-11-dedalus-sdk-pydantic-v2' or extra != 'group-11-dedalus-sdk-pydantic-v1'" }, - { name = "sniffio" }, - { name = "typing-extensions" }, -] - -[package.optional-dependencies] -aiohttp = [ - { name = "aiohttp" }, - { name = "httpx-aiohttp" }, -] - -[package.dev-dependencies] -dev = [ - { name = "dirty-equals" }, - { name = "importlib-metadata" }, - { name = "mypy" }, - { name = "pyright" }, - { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pytest-asyncio", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pytest-asyncio", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pytest-xdist" }, - { name = "respx" }, - { name = "rich" }, - { name = "ruff" }, - { name = "time-machine", version = "2.19.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "time-machine", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -pydantic-v1 = [ - { name = "pydantic", version = "1.10.26", source = { registry = "https://pypi.org/simple" } }, -] -pydantic-v2 = [ - { name = "pydantic", version = "2.12.5", source = { registry = "https://pypi.org/simple" } }, -] - -[package.metadata] -requires-dist = [ - { name = "aiohttp", marker = "extra == 'aiohttp'" }, - { name = "anyio", specifier = ">=3.5.0,<5" }, - { name = "distro", specifier = ">=1.7.0,<2" }, - { name = "httpx", specifier = ">=0.23.0,<1" }, - { name = "httpx-aiohttp", marker = "extra == 'aiohttp'", specifier = ">=0.1.9" }, - { name = "pydantic", specifier = ">=1.9.0,<3" }, - { name = "sniffio" }, - { name = "typing-extensions", specifier = ">=4.14,<5" }, -] -provides-extras = ["aiohttp"] - -[package.metadata.requires-dev] -dev = [ - { name = "dirty-equals", specifier = ">=0.6.0" }, - { name = "importlib-metadata", specifier = ">=6.7.0" }, - { name = "mypy", specifier = "==1.17" }, - { name = "pyright", specifier = "==1.1.399" }, - { name = "pytest" }, - { name = "pytest-asyncio" }, - { name = "pytest-xdist", specifier = ">=3.6.1" }, - { name = "respx" }, - { name = "rich", specifier = ">=13.7.1" }, - { name = "ruff" }, - { name = "time-machine" }, -] -pydantic-v1 = [{ name = "pydantic", specifier = ">=1.9.0,<2" }] -pydantic-v2 = [ - { name = "pydantic", marker = "python_full_version < '3.14'", specifier = "~=2.0" }, - { name = "pydantic", marker = "python_full_version >= '3.14'", specifier = "~=2.12" }, -] - -[[package]] -name = "dirty-equals" -version = "0.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/1d/c5913ac9d6615515a00f4bdc71356d302437cb74ff2e9aaccd3c14493b78/dirty_equals-0.11.tar.gz", hash = "sha256:f4ac74ee88f2d11e2fa0f65eb30ee4f07105c5f86f4dc92b09eb1138775027c3", size = 128067, upload-time = "2025-11-17T01:51:24.451Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/8d/dbff05239043271dbeace563a7686212a3dd517864a35623fe4d4a64ca19/dirty_equals-0.11-py3-none-any.whl", hash = "sha256:b1d7093273fc2f9be12f443a8ead954ef6daaf6746fd42ef3a5616433ee85286", size = 28051, upload-time = "2025-11-17T01:51:22.849Z" }, -] - -[[package]] -name = "distro" -version = "1.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, -] - -[[package]] -name = "exceptiongroup" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, -] - -[[package]] -name = "execnet" -version = "2.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, -] - -[[package]] -name = "frozenlist" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/4a/557715d5047da48d54e659203b9335be7bfaafda2c3f627b7c47e0b3aaf3/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", size = 86230, upload-time = "2025-10-06T05:35:23.699Z" }, - { url = "https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", size = 49621, upload-time = "2025-10-06T05:35:25.341Z" }, - { url = "https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", size = 49889, upload-time = "2025-10-06T05:35:26.797Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", size = 219464, upload-time = "2025-10-06T05:35:28.254Z" }, - { url = "https://files.pythonhosted.org/packages/6b/83/4d587dccbfca74cb8b810472392ad62bfa100bf8108c7223eb4c4fa2f7b3/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", size = 221649, upload-time = "2025-10-06T05:35:29.454Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c6/fd3b9cd046ec5fff9dab66831083bc2077006a874a2d3d9247dea93ddf7e/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", size = 219188, upload-time = "2025-10-06T05:35:30.951Z" }, - { url = "https://files.pythonhosted.org/packages/ce/80/6693f55eb2e085fc8afb28cf611448fb5b90e98e068fa1d1b8d8e66e5c7d/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", size = 231748, upload-time = "2025-10-06T05:35:32.101Z" }, - { url = "https://files.pythonhosted.org/packages/97/d6/e9459f7c5183854abd989ba384fe0cc1a0fb795a83c033f0571ec5933ca4/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", size = 236351, upload-time = "2025-10-06T05:35:33.834Z" }, - { url = "https://files.pythonhosted.org/packages/97/92/24e97474b65c0262e9ecd076e826bfd1d3074adcc165a256e42e7b8a7249/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", size = 218767, upload-time = "2025-10-06T05:35:35.205Z" }, - { url = "https://files.pythonhosted.org/packages/ee/bf/dc394a097508f15abff383c5108cb8ad880d1f64a725ed3b90d5c2fbf0bb/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", size = 235887, upload-time = "2025-10-06T05:35:36.354Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/25b201b9c015dbc999a5baf475a257010471a1fa8c200c843fd4abbee725/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", size = 228785, upload-time = "2025-10-06T05:35:37.949Z" }, - { url = "https://files.pythonhosted.org/packages/84/f4/b5bc148df03082f05d2dd30c089e269acdbe251ac9a9cf4e727b2dbb8a3d/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", size = 230312, upload-time = "2025-10-06T05:35:39.178Z" }, - { url = "https://files.pythonhosted.org/packages/db/4b/87e95b5d15097c302430e647136b7d7ab2398a702390cf4c8601975709e7/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", size = 217650, upload-time = "2025-10-06T05:35:40.377Z" }, - { url = "https://files.pythonhosted.org/packages/e5/70/78a0315d1fea97120591a83e0acd644da638c872f142fd72a6cebee825f3/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", size = 39659, upload-time = "2025-10-06T05:35:41.863Z" }, - { url = "https://files.pythonhosted.org/packages/66/aa/3f04523fb189a00e147e60c5b2205126118f216b0aa908035c45336e27e4/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", size = 43837, upload-time = "2025-10-06T05:35:43.205Z" }, - { url = "https://files.pythonhosted.org/packages/39/75/1135feecdd7c336938bd55b4dc3b0dfc46d85b9be12ef2628574b28de776/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", size = 39989, upload-time = "2025-10-06T05:35:44.596Z" }, - { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, - { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, - { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, - { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, - { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, - { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, - { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, - { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, - { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, - { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, - { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, - { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, - { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, - { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, - { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, - { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, - { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, - { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, - { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, - { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, - { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, - { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, - { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, - { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, - { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, - { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, - { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, - { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, - { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, - { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, - { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, - { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, - { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, - { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, - { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, - { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, - { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, - { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, - { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, - { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, - { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, - { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, - { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, - { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, - { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, - { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, - { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, - { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, - { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, - { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, - { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, - { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, - { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, - { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, - { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, - { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, - { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, - { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, - { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, - { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, - { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, - { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, - { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, - { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, - { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, - { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, - { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, - { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, - { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, - { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, - { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, - { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, - { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, - { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, - { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, - { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, - { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, - { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, - { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, - { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, - { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, - { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, - { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, - { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, - { url = "https://files.pythonhosted.org/packages/c2/59/ae5cdac87a00962122ea37bb346d41b66aec05f9ce328fa2b9e216f8967b/frozenlist-1.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47", size = 86967, upload-time = "2025-10-06T05:37:55.607Z" }, - { url = "https://files.pythonhosted.org/packages/8a/10/17059b2db5a032fd9323c41c39e9d1f5f9d0c8f04d1e4e3e788573086e61/frozenlist-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca", size = 49984, upload-time = "2025-10-06T05:37:57.049Z" }, - { url = "https://files.pythonhosted.org/packages/4b/de/ad9d82ca8e5fa8f0c636e64606553c79e2b859ad253030b62a21fe9986f5/frozenlist-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068", size = 50240, upload-time = "2025-10-06T05:37:58.145Z" }, - { url = "https://files.pythonhosted.org/packages/4e/45/3dfb7767c2a67d123650122b62ce13c731b6c745bc14424eea67678b508c/frozenlist-1.8.0-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95", size = 219472, upload-time = "2025-10-06T05:37:59.239Z" }, - { url = "https://files.pythonhosted.org/packages/0b/bf/5bf23d913a741b960d5c1dac7c1985d8a2a1d015772b2d18ea168b08e7ff/frozenlist-1.8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459", size = 221531, upload-time = "2025-10-06T05:38:00.521Z" }, - { url = "https://files.pythonhosted.org/packages/d0/03/27ec393f3b55860859f4b74cdc8c2a4af3dbf3533305e8eacf48a4fd9a54/frozenlist-1.8.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675", size = 219211, upload-time = "2025-10-06T05:38:01.842Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ad/0fd00c404fa73fe9b169429e9a972d5ed807973c40ab6b3cf9365a33d360/frozenlist-1.8.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61", size = 231775, upload-time = "2025-10-06T05:38:03.384Z" }, - { url = "https://files.pythonhosted.org/packages/8a/c3/86962566154cb4d2995358bc8331bfc4ea19d07db1a96f64935a1607f2b6/frozenlist-1.8.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6", size = 236631, upload-time = "2025-10-06T05:38:04.609Z" }, - { url = "https://files.pythonhosted.org/packages/ea/9e/6ffad161dbd83782d2c66dc4d378a9103b31770cb1e67febf43aea42d202/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5", size = 218632, upload-time = "2025-10-06T05:38:05.917Z" }, - { url = "https://files.pythonhosted.org/packages/58/b2/4677eee46e0a97f9b30735e6ad0bf6aba3e497986066eb68807ac85cf60f/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3", size = 235967, upload-time = "2025-10-06T05:38:07.614Z" }, - { url = "https://files.pythonhosted.org/packages/05/f3/86e75f8639c5a93745ca7addbbc9de6af56aebb930d233512b17e46f6493/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1", size = 228799, upload-time = "2025-10-06T05:38:08.845Z" }, - { url = "https://files.pythonhosted.org/packages/30/00/39aad3a7f0d98f5eb1d99a3c311215674ed87061aecee7851974b335c050/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178", size = 230566, upload-time = "2025-10-06T05:38:10.52Z" }, - { url = "https://files.pythonhosted.org/packages/0d/4d/aa144cac44568d137846ddc4d5210fb5d9719eb1d7ec6fa2728a54b5b94a/frozenlist-1.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda", size = 217715, upload-time = "2025-10-06T05:38:11.832Z" }, - { url = "https://files.pythonhosted.org/packages/64/4c/8f665921667509d25a0dd72540513bc86b356c95541686f6442a3283019f/frozenlist-1.8.0-cp39-cp39-win32.whl", hash = "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087", size = 39933, upload-time = "2025-10-06T05:38:13.061Z" }, - { url = "https://files.pythonhosted.org/packages/79/bd/bcc926f87027fad5e59926ff12d136e1082a115025d33c032d1cd69ab377/frozenlist-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a", size = 44121, upload-time = "2025-10-06T05:38:14.572Z" }, - { url = "https://files.pythonhosted.org/packages/4c/07/9c2e4eb7584af4b705237b971b89a4155a8e57599c4483a131a39256a9a0/frozenlist-1.8.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103", size = 40312, upload-time = "2025-10-06T05:38:15.699Z" }, - { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, -] - -[[package]] -name = "h11" -version = "0.16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, -] - -[[package]] -name = "httpx" -version = "0.28.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, -] - -[[package]] -name = "httpx-aiohttp" -version = "0.1.12" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohttp" }, - { name = "httpx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/63/2c/b894861cecf030fb45675ea24aa55b5722e97c602a163d872fca66c5a6d8/httpx_aiohttp-0.1.12.tar.gz", hash = "sha256:81feec51fd82c0ecfa0e9aaf1b1a6c2591260d5e2bcbeb7eb0277a78e610df2c", size = 275945, upload-time = "2025-12-12T10:12:15.283Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/16/8d/85c9701e9af72ca132a1783e2a54364a90c6da832304416a30fc11196ab2/httpx_aiohttp-0.1.12-py3-none-any.whl", hash = "sha256:5b0eac39a7f360fa7867a60bcb46bb1024eada9c01cbfecdb54dc1edb3fb7141", size = 6367, upload-time = "2025-12-12T10:12:14.018Z" }, -] - -[[package]] -name = "idna" -version = "3.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, -] - -[[package]] -name = "importlib-metadata" -version = "8.7.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "zipp" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, -] - -[[package]] -name = "iniconfig" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, -] - -[[package]] -name = "iniconfig" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", -] -sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, -] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "mdurl", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, -] - -[[package]] -name = "markdown-it-py" -version = "4.0.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", -] -dependencies = [ - { name = "mdurl", marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, -] - -[[package]] -name = "mdurl" -version = "0.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, -] - -[[package]] -name = "multidict" -version = "6.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/63/7bdd4adc330abcca54c85728db2327130e49e52e8c3ce685cec44e0f2e9f/multidict-6.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349", size = 77153, upload-time = "2025-10-06T14:48:26.409Z" }, - { url = "https://files.pythonhosted.org/packages/3f/bb/b6c35ff175ed1a3142222b78455ee31be71a8396ed3ab5280fbe3ebe4e85/multidict-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e", size = 44993, upload-time = "2025-10-06T14:48:28.4Z" }, - { url = "https://files.pythonhosted.org/packages/e0/1f/064c77877c5fa6df6d346e68075c0f6998547afe952d6471b4c5f6a7345d/multidict-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3", size = 44607, upload-time = "2025-10-06T14:48:29.581Z" }, - { url = "https://files.pythonhosted.org/packages/04/7a/bf6aa92065dd47f287690000b3d7d332edfccb2277634cadf6a810463c6a/multidict-6.7.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046", size = 241847, upload-time = "2025-10-06T14:48:32.107Z" }, - { url = "https://files.pythonhosted.org/packages/94/39/297a8de920f76eda343e4ce05f3b489f0ab3f9504f2576dfb37b7c08ca08/multidict-6.7.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32", size = 242616, upload-time = "2025-10-06T14:48:34.054Z" }, - { url = "https://files.pythonhosted.org/packages/39/3a/d0eee2898cfd9d654aea6cb8c4addc2f9756e9a7e09391cfe55541f917f7/multidict-6.7.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73", size = 222333, upload-time = "2025-10-06T14:48:35.9Z" }, - { url = "https://files.pythonhosted.org/packages/05/48/3b328851193c7a4240815b71eea165b49248867bbb6153a0aee227a0bb47/multidict-6.7.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc", size = 253239, upload-time = "2025-10-06T14:48:37.302Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ca/0706a98c8d126a89245413225ca4a3fefc8435014de309cf8b30acb68841/multidict-6.7.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62", size = 251618, upload-time = "2025-10-06T14:48:38.963Z" }, - { url = "https://files.pythonhosted.org/packages/5e/4f/9c7992f245554d8b173f6f0a048ad24b3e645d883f096857ec2c0822b8bd/multidict-6.7.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84", size = 241655, upload-time = "2025-10-06T14:48:40.312Z" }, - { url = "https://files.pythonhosted.org/packages/31/79/26a85991ae67efd1c0b1fc2e0c275b8a6aceeb155a68861f63f87a798f16/multidict-6.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0", size = 239245, upload-time = "2025-10-06T14:48:41.848Z" }, - { url = "https://files.pythonhosted.org/packages/14/1e/75fa96394478930b79d0302eaf9a6c69f34005a1a5251ac8b9c336486ec9/multidict-6.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e", size = 233523, upload-time = "2025-10-06T14:48:43.749Z" }, - { url = "https://files.pythonhosted.org/packages/b2/5e/085544cb9f9c4ad2b5d97467c15f856df8d9bac410cffd5c43991a5d878b/multidict-6.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4", size = 243129, upload-time = "2025-10-06T14:48:45.225Z" }, - { url = "https://files.pythonhosted.org/packages/b9/c3/e9d9e2f20c9474e7a8fcef28f863c5cbd29bb5adce6b70cebe8bdad0039d/multidict-6.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648", size = 248999, upload-time = "2025-10-06T14:48:46.703Z" }, - { url = "https://files.pythonhosted.org/packages/b5/3f/df171b6efa3239ae33b97b887e42671cd1d94d460614bfb2c30ffdab3b95/multidict-6.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111", size = 243711, upload-time = "2025-10-06T14:48:48.146Z" }, - { url = "https://files.pythonhosted.org/packages/3c/2f/9b5564888c4e14b9af64c54acf149263721a283aaf4aa0ae89b091d5d8c1/multidict-6.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36", size = 237504, upload-time = "2025-10-06T14:48:49.447Z" }, - { url = "https://files.pythonhosted.org/packages/6c/3a/0bd6ca0f7d96d790542d591c8c3354c1e1b6bfd2024d4d92dc3d87485ec7/multidict-6.7.0-cp310-cp310-win32.whl", hash = "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85", size = 41422, upload-time = "2025-10-06T14:48:50.789Z" }, - { url = "https://files.pythonhosted.org/packages/00/35/f6a637ea2c75f0d3b7c7d41b1189189acff0d9deeb8b8f35536bb30f5e33/multidict-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7", size = 46050, upload-time = "2025-10-06T14:48:51.938Z" }, - { url = "https://files.pythonhosted.org/packages/e7/b8/f7bf8329b39893d02d9d95cf610c75885d12fc0f402b1c894e1c8e01c916/multidict-6.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0", size = 43153, upload-time = "2025-10-06T14:48:53.146Z" }, - { url = "https://files.pythonhosted.org/packages/34/9e/5c727587644d67b2ed479041e4b1c58e30afc011e3d45d25bbe35781217c/multidict-6.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc", size = 76604, upload-time = "2025-10-06T14:48:54.277Z" }, - { url = "https://files.pythonhosted.org/packages/17/e4/67b5c27bd17c085a5ea8f1ec05b8a3e5cba0ca734bfcad5560fb129e70ca/multidict-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721", size = 44715, upload-time = "2025-10-06T14:48:55.445Z" }, - { url = "https://files.pythonhosted.org/packages/4d/e1/866a5d77be6ea435711bef2a4291eed11032679b6b28b56b4776ab06ba3e/multidict-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6", size = 44332, upload-time = "2025-10-06T14:48:56.706Z" }, - { url = "https://files.pythonhosted.org/packages/31/61/0c2d50241ada71ff61a79518db85ada85fdabfcf395d5968dae1cbda04e5/multidict-6.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c", size = 245212, upload-time = "2025-10-06T14:48:58.042Z" }, - { url = "https://files.pythonhosted.org/packages/ac/e0/919666a4e4b57fff1b57f279be1c9316e6cdc5de8a8b525d76f6598fefc7/multidict-6.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7", size = 246671, upload-time = "2025-10-06T14:49:00.004Z" }, - { url = "https://files.pythonhosted.org/packages/a1/cc/d027d9c5a520f3321b65adea289b965e7bcbd2c34402663f482648c716ce/multidict-6.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7", size = 225491, upload-time = "2025-10-06T14:49:01.393Z" }, - { url = "https://files.pythonhosted.org/packages/75/c4/bbd633980ce6155a28ff04e6a6492dd3335858394d7bb752d8b108708558/multidict-6.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9", size = 257322, upload-time = "2025-10-06T14:49:02.745Z" }, - { url = "https://files.pythonhosted.org/packages/4c/6d/d622322d344f1f053eae47e033b0b3f965af01212de21b10bcf91be991fb/multidict-6.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8", size = 254694, upload-time = "2025-10-06T14:49:04.15Z" }, - { url = "https://files.pythonhosted.org/packages/a8/9f/78f8761c2705d4c6d7516faed63c0ebdac569f6db1bef95e0d5218fdc146/multidict-6.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd", size = 246715, upload-time = "2025-10-06T14:49:05.967Z" }, - { url = "https://files.pythonhosted.org/packages/78/59/950818e04f91b9c2b95aab3d923d9eabd01689d0dcd889563988e9ea0fd8/multidict-6.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb", size = 243189, upload-time = "2025-10-06T14:49:07.37Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3d/77c79e1934cad2ee74991840f8a0110966d9599b3af95964c0cd79bb905b/multidict-6.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6", size = 237845, upload-time = "2025-10-06T14:49:08.759Z" }, - { url = "https://files.pythonhosted.org/packages/63/1b/834ce32a0a97a3b70f86437f685f880136677ac00d8bce0027e9fd9c2db7/multidict-6.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2", size = 246374, upload-time = "2025-10-06T14:49:10.574Z" }, - { url = "https://files.pythonhosted.org/packages/23/ef/43d1c3ba205b5dec93dc97f3fba179dfa47910fc73aaaea4f7ceb41cec2a/multidict-6.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff", size = 253345, upload-time = "2025-10-06T14:49:12.331Z" }, - { url = "https://files.pythonhosted.org/packages/6b/03/eaf95bcc2d19ead522001f6a650ef32811aa9e3624ff0ad37c445c7a588c/multidict-6.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b", size = 246940, upload-time = "2025-10-06T14:49:13.821Z" }, - { url = "https://files.pythonhosted.org/packages/e8/df/ec8a5fd66ea6cd6f525b1fcbb23511b033c3e9bc42b81384834ffa484a62/multidict-6.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34", size = 242229, upload-time = "2025-10-06T14:49:15.603Z" }, - { url = "https://files.pythonhosted.org/packages/8a/a2/59b405d59fd39ec86d1142630e9049243015a5f5291ba49cadf3c090c541/multidict-6.7.0-cp311-cp311-win32.whl", hash = "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff", size = 41308, upload-time = "2025-10-06T14:49:16.871Z" }, - { url = "https://files.pythonhosted.org/packages/32/0f/13228f26f8b882c34da36efa776c3b7348455ec383bab4a66390e42963ae/multidict-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81", size = 46037, upload-time = "2025-10-06T14:49:18.457Z" }, - { url = "https://files.pythonhosted.org/packages/84/1f/68588e31b000535a3207fd3c909ebeec4fb36b52c442107499c18a896a2a/multidict-6.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912", size = 43023, upload-time = "2025-10-06T14:49:19.648Z" }, - { url = "https://files.pythonhosted.org/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, - { url = "https://files.pythonhosted.org/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, - { url = "https://files.pythonhosted.org/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, - { url = "https://files.pythonhosted.org/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, - { url = "https://files.pythonhosted.org/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, - { url = "https://files.pythonhosted.org/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, - { url = "https://files.pythonhosted.org/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, - { url = "https://files.pythonhosted.org/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, - { url = "https://files.pythonhosted.org/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, - { url = "https://files.pythonhosted.org/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, - { url = "https://files.pythonhosted.org/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, - { url = "https://files.pythonhosted.org/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, - { url = "https://files.pythonhosted.org/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, - { url = "https://files.pythonhosted.org/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, - { url = "https://files.pythonhosted.org/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, - { url = "https://files.pythonhosted.org/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, - { url = "https://files.pythonhosted.org/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, - { url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, - { url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, - { url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, - { url = "https://files.pythonhosted.org/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, - { url = "https://files.pythonhosted.org/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, - { url = "https://files.pythonhosted.org/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, - { url = "https://files.pythonhosted.org/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, - { url = "https://files.pythonhosted.org/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, - { url = "https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, - { url = "https://files.pythonhosted.org/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, - { url = "https://files.pythonhosted.org/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, - { url = "https://files.pythonhosted.org/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, - { url = "https://files.pythonhosted.org/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, - { url = "https://files.pythonhosted.org/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, - { url = "https://files.pythonhosted.org/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, - { url = "https://files.pythonhosted.org/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, - { url = "https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, - { url = "https://files.pythonhosted.org/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, - { url = "https://files.pythonhosted.org/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, - { url = "https://files.pythonhosted.org/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, - { url = "https://files.pythonhosted.org/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, - { url = "https://files.pythonhosted.org/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, - { url = "https://files.pythonhosted.org/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, - { url = "https://files.pythonhosted.org/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, - { url = "https://files.pythonhosted.org/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, - { url = "https://files.pythonhosted.org/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, - { url = "https://files.pythonhosted.org/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, - { url = "https://files.pythonhosted.org/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, - { url = "https://files.pythonhosted.org/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, - { url = "https://files.pythonhosted.org/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, - { url = "https://files.pythonhosted.org/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, - { url = "https://files.pythonhosted.org/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, - { url = "https://files.pythonhosted.org/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, - { url = "https://files.pythonhosted.org/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, - { url = "https://files.pythonhosted.org/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, - { url = "https://files.pythonhosted.org/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b1/3da6934455dd4b261d4c72f897e3a5728eba81db59959f3a639245891baa/multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", size = 75128, upload-time = "2025-10-06T14:50:51.92Z" }, - { url = "https://files.pythonhosted.org/packages/14/2c/f069cab5b51d175a1a2cb4ccdf7a2c2dabd58aa5bd933fa036a8d15e2404/multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", size = 44410, upload-time = "2025-10-06T14:50:53.275Z" }, - { url = "https://files.pythonhosted.org/packages/42/e2/64bb41266427af6642b6b128e8774ed84c11b80a90702c13ac0a86bb10cc/multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", size = 43205, upload-time = "2025-10-06T14:50:54.911Z" }, - { url = "https://files.pythonhosted.org/packages/02/68/6b086fef8a3f1a8541b9236c594f0c9245617c29841f2e0395d979485cde/multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", size = 245084, upload-time = "2025-10-06T14:50:56.369Z" }, - { url = "https://files.pythonhosted.org/packages/15/ee/f524093232007cd7a75c1d132df70f235cfd590a7c9eaccd7ff422ef4ae8/multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", size = 252667, upload-time = "2025-10-06T14:50:57.991Z" }, - { url = "https://files.pythonhosted.org/packages/02/a5/eeb3f43ab45878f1895118c3ef157a480db58ede3f248e29b5354139c2c9/multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", size = 233590, upload-time = "2025-10-06T14:50:59.589Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1e/76d02f8270b97269d7e3dbd45644b1785bda457b474315f8cf999525a193/multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", size = 264112, upload-time = "2025-10-06T14:51:01.183Z" }, - { url = "https://files.pythonhosted.org/packages/76/0b/c28a70ecb58963847c2a8efe334904cd254812b10e535aefb3bcce513918/multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", size = 261194, upload-time = "2025-10-06T14:51:02.794Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/2ab26e4209773223159b83aa32721b4021ffb08102f8ac7d689c943fded1/multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", size = 248510, upload-time = "2025-10-06T14:51:04.724Z" }, - { url = "https://files.pythonhosted.org/packages/93/cd/06c1fa8282af1d1c46fd55c10a7930af652afdce43999501d4d68664170c/multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", size = 248395, upload-time = "2025-10-06T14:51:06.306Z" }, - { url = "https://files.pythonhosted.org/packages/99/ac/82cb419dd6b04ccf9e7e61befc00c77614fc8134362488b553402ecd55ce/multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", size = 239520, upload-time = "2025-10-06T14:51:08.091Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f3/a0f9bf09493421bd8716a362e0cd1d244f5a6550f5beffdd6b47e885b331/multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7", size = 245479, upload-time = "2025-10-06T14:51:10.365Z" }, - { url = "https://files.pythonhosted.org/packages/8d/01/476d38fc73a212843f43c852b0eee266b6971f0e28329c2184a8df90c376/multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", size = 258903, upload-time = "2025-10-06T14:51:12.466Z" }, - { url = "https://files.pythonhosted.org/packages/49/6d/23faeb0868adba613b817d0e69c5f15531b24d462af8012c4f6de4fa8dc3/multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", size = 252333, upload-time = "2025-10-06T14:51:14.48Z" }, - { url = "https://files.pythonhosted.org/packages/1e/cc/48d02ac22b30fa247f7dad82866e4b1015431092f4ba6ebc7e77596e0b18/multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", size = 243411, upload-time = "2025-10-06T14:51:16.072Z" }, - { url = "https://files.pythonhosted.org/packages/4a/03/29a8bf5a18abf1fe34535c88adbdfa88c9fb869b5a3b120692c64abe8284/multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", size = 40940, upload-time = "2025-10-06T14:51:17.544Z" }, - { url = "https://files.pythonhosted.org/packages/82/16/7ed27b680791b939de138f906d5cf2b4657b0d45ca6f5dd6236fdddafb1a/multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", size = 45087, upload-time = "2025-10-06T14:51:18.875Z" }, - { url = "https://files.pythonhosted.org/packages/cd/3c/e3e62eb35a1950292fe39315d3c89941e30a9d07d5d2df42965ab041da43/multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", size = 42368, upload-time = "2025-10-06T14:51:20.225Z" }, - { url = "https://files.pythonhosted.org/packages/8b/40/cd499bd0dbc5f1136726db3153042a735fffd0d77268e2ee20d5f33c010f/multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", size = 82326, upload-time = "2025-10-06T14:51:21.588Z" }, - { url = "https://files.pythonhosted.org/packages/13/8a/18e031eca251c8df76daf0288e6790561806e439f5ce99a170b4af30676b/multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", size = 48065, upload-time = "2025-10-06T14:51:22.93Z" }, - { url = "https://files.pythonhosted.org/packages/40/71/5e6701277470a87d234e433fb0a3a7deaf3bcd92566e421e7ae9776319de/multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", size = 46475, upload-time = "2025-10-06T14:51:24.352Z" }, - { url = "https://files.pythonhosted.org/packages/fe/6a/bab00cbab6d9cfb57afe1663318f72ec28289ea03fd4e8236bb78429893a/multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", size = 239324, upload-time = "2025-10-06T14:51:25.822Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5f/8de95f629fc22a7769ade8b41028e3e5a822c1f8904f618d175945a81ad3/multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", size = 246877, upload-time = "2025-10-06T14:51:27.604Z" }, - { url = "https://files.pythonhosted.org/packages/23/b4/38881a960458f25b89e9f4a4fdcb02ac101cfa710190db6e5528841e67de/multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", size = 225824, upload-time = "2025-10-06T14:51:29.664Z" }, - { url = "https://files.pythonhosted.org/packages/1e/39/6566210c83f8a261575f18e7144736059f0c460b362e96e9cf797a24b8e7/multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", size = 253558, upload-time = "2025-10-06T14:51:31.684Z" }, - { url = "https://files.pythonhosted.org/packages/00/a3/67f18315100f64c269f46e6c0319fa87ba68f0f64f2b8e7fd7c72b913a0b/multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", size = 252339, upload-time = "2025-10-06T14:51:33.699Z" }, - { url = "https://files.pythonhosted.org/packages/c8/2a/1cb77266afee2458d82f50da41beba02159b1d6b1f7973afc9a1cad1499b/multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", size = 244895, upload-time = "2025-10-06T14:51:36.189Z" }, - { url = "https://files.pythonhosted.org/packages/dd/72/09fa7dd487f119b2eb9524946ddd36e2067c08510576d43ff68469563b3b/multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", size = 241862, upload-time = "2025-10-06T14:51:41.291Z" }, - { url = "https://files.pythonhosted.org/packages/65/92/bc1f8bd0853d8669300f732c801974dfc3702c3eeadae2f60cef54dc69d7/multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", size = 232376, upload-time = "2025-10-06T14:51:43.55Z" }, - { url = "https://files.pythonhosted.org/packages/09/86/ac39399e5cb9d0c2ac8ef6e10a768e4d3bc933ac808d49c41f9dc23337eb/multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", size = 240272, upload-time = "2025-10-06T14:51:45.265Z" }, - { url = "https://files.pythonhosted.org/packages/3d/b6/fed5ac6b8563ec72df6cb1ea8dac6d17f0a4a1f65045f66b6d3bf1497c02/multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", size = 248774, upload-time = "2025-10-06T14:51:46.836Z" }, - { url = "https://files.pythonhosted.org/packages/6b/8d/b954d8c0dc132b68f760aefd45870978deec6818897389dace00fcde32ff/multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", size = 242731, upload-time = "2025-10-06T14:51:48.541Z" }, - { url = "https://files.pythonhosted.org/packages/16/9d/a2dac7009125d3540c2f54e194829ea18ac53716c61b655d8ed300120b0f/multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", size = 240193, upload-time = "2025-10-06T14:51:50.355Z" }, - { url = "https://files.pythonhosted.org/packages/39/ca/c05f144128ea232ae2178b008d5011d4e2cea86e4ee8c85c2631b1b94802/multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", size = 48023, upload-time = "2025-10-06T14:51:51.883Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8f/0a60e501584145588be1af5cc829265701ba3c35a64aec8e07cbb71d39bb/multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", size = 53507, upload-time = "2025-10-06T14:51:53.672Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ae/3148b988a9c6239903e786eac19c889fab607c31d6efa7fb2147e5680f23/multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", size = 44804, upload-time = "2025-10-06T14:51:55.415Z" }, - { url = "https://files.pythonhosted.org/packages/90/d7/4cf84257902265c4250769ac49f4eaab81c182ee9aff8bf59d2714dbb174/multidict-6.7.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:363eb68a0a59bd2303216d2346e6c441ba10d36d1f9969fcb6f1ba700de7bb5c", size = 77073, upload-time = "2025-10-06T14:51:57.386Z" }, - { url = "https://files.pythonhosted.org/packages/6d/51/194e999630a656e76c2965a1590d12faa5cd528170f2abaa04423e09fe8d/multidict-6.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d874eb056410ca05fed180b6642e680373688efafc7f077b2a2f61811e873a40", size = 44928, upload-time = "2025-10-06T14:51:58.791Z" }, - { url = "https://files.pythonhosted.org/packages/e5/6b/2a195373c33068c9158e0941d0b46cfcc9c1d894ca2eb137d1128081dff0/multidict-6.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b55d5497b51afdfde55925e04a022f1de14d4f4f25cdfd4f5d9b0aa96166851", size = 44581, upload-time = "2025-10-06T14:52:00.174Z" }, - { url = "https://files.pythonhosted.org/packages/69/7b/7f4f2e644b6978bf011a5fd9a5ebb7c21de3f38523b1f7897d36a1ac1311/multidict-6.7.0-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f8e5c0031b90ca9ce555e2e8fd5c3b02a25f14989cbc310701823832c99eb687", size = 239901, upload-time = "2025-10-06T14:52:02.416Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b5/952c72786710a031aa204a9adf7db66d7f97a2c6573889d58b9e60fe6702/multidict-6.7.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cf41880c991716f3c7cec48e2f19ae4045fc9db5fc9cff27347ada24d710bb5", size = 240534, upload-time = "2025-10-06T14:52:04.105Z" }, - { url = "https://files.pythonhosted.org/packages/f3/ef/109fe1f2471e4c458c74242c7e4a833f2d9fc8a6813cd7ee345b0bad18f9/multidict-6.7.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cfc12a8630a29d601f48d47787bd7eb730e475e83edb5d6c5084317463373eb", size = 219545, upload-time = "2025-10-06T14:52:06.208Z" }, - { url = "https://files.pythonhosted.org/packages/42/bd/327d91288114967f9fe90dc53de70aa3fec1b9073e46aa32c4828f771a87/multidict-6.7.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3996b50c3237c4aec17459217c1e7bbdead9a22a0fcd3c365564fbd16439dde6", size = 251187, upload-time = "2025-10-06T14:52:08.049Z" }, - { url = "https://files.pythonhosted.org/packages/f4/13/a8b078ebbaceb7819fd28cd004413c33b98f1b70d542a62e6a00b74fb09f/multidict-6.7.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7f5170993a0dd3ab871c74f45c0a21a4e2c37a2f2b01b5f722a2ad9c6650469e", size = 249379, upload-time = "2025-10-06T14:52:09.831Z" }, - { url = "https://files.pythonhosted.org/packages/e3/6d/ab12e1246be4d65d1f55de1e6f6aaa9b8120eddcfdd1d290439c7833d5ce/multidict-6.7.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ec81878ddf0e98817def1e77d4f50dae5ef5b0e4fe796fae3bd674304172416e", size = 239241, upload-time = "2025-10-06T14:52:11.561Z" }, - { url = "https://files.pythonhosted.org/packages/bb/d7/079a93625208c173b8fa756396814397c0fd9fee61ef87b75a748820b86e/multidict-6.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9281bf5b34f59afbc6b1e477a372e9526b66ca446f4bf62592839c195a718b32", size = 237418, upload-time = "2025-10-06T14:52:13.671Z" }, - { url = "https://files.pythonhosted.org/packages/c9/29/03777c2212274aa9440918d604dc9d6af0e6b4558c611c32c3dcf1a13870/multidict-6.7.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:68af405971779d8b37198726f2b6fe3955db846fee42db7a4286fc542203934c", size = 232987, upload-time = "2025-10-06T14:52:15.708Z" }, - { url = "https://files.pythonhosted.org/packages/d9/00/11188b68d85a84e8050ee34724d6ded19ad03975caebe0c8dcb2829b37bf/multidict-6.7.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3ba3ef510467abb0667421a286dc906e30eb08569365f5cdb131d7aff7c2dd84", size = 240985, upload-time = "2025-10-06T14:52:17.317Z" }, - { url = "https://files.pythonhosted.org/packages/df/0c/12eef6aeda21859c6cdf7d75bd5516d83be3efe3d8cc45fd1a3037f5b9dc/multidict-6.7.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b61189b29081a20c7e4e0b49b44d5d44bb0dc92be3c6d06a11cc043f81bf9329", size = 246855, upload-time = "2025-10-06T14:52:19.096Z" }, - { url = "https://files.pythonhosted.org/packages/69/f6/076120fd8bb3975f09228e288e08bff6b9f1bfd5166397c7ba284f622ab2/multidict-6.7.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fb287618b9c7aa3bf8d825f02d9201b2f13078a5ed3b293c8f4d953917d84d5e", size = 241804, upload-time = "2025-10-06T14:52:21.166Z" }, - { url = "https://files.pythonhosted.org/packages/5f/51/41bb950c81437b88a93e6ddfca1d8763569ae861e638442838c4375f7497/multidict-6.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:521f33e377ff64b96c4c556b81c55d0cfffb96a11c194fd0c3f1e56f3d8dd5a4", size = 235321, upload-time = "2025-10-06T14:52:23.208Z" }, - { url = "https://files.pythonhosted.org/packages/5a/cf/5bbd31f055199d56c1f6b04bbadad3ccb24e6d5d4db75db774fc6d6674b8/multidict-6.7.0-cp39-cp39-win32.whl", hash = "sha256:ce8fdc2dca699f8dbf055a61d73eaa10482569ad20ee3c36ef9641f69afa8c91", size = 41435, upload-time = "2025-10-06T14:52:24.735Z" }, - { url = "https://files.pythonhosted.org/packages/af/01/547ffe9c2faec91c26965c152f3fea6cff068b6037401f61d310cc861ff4/multidict-6.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:7e73299c99939f089dd9b2120a04a516b95cdf8c1cd2b18c53ebf0de80b1f18f", size = 46193, upload-time = "2025-10-06T14:52:26.101Z" }, - { url = "https://files.pythonhosted.org/packages/27/77/cfa5461d1d2651d6fc24216c92b4a21d4e385a41c46e0d9f3b070675167b/multidict-6.7.0-cp39-cp39-win_arm64.whl", hash = "sha256:6bdce131e14b04fd34a809b6380dbfd826065c3e2fe8a50dbae659fa0c390546", size = 43118, upload-time = "2025-10-06T14:52:27.876Z" }, - { url = "https://files.pythonhosted.org/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, -] - -[[package]] -name = "mypy" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mypy-extensions" }, - { name = "pathspec" }, - { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1e/e3/034322d5a779685218ed69286c32faa505247f1f096251ef66c8fd203b08/mypy-1.17.0.tar.gz", hash = "sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03", size = 3352114, upload-time = "2025-07-14T20:34:30.181Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/31/e762baa3b73905c856d45ab77b4af850e8159dffffd86a52879539a08c6b/mypy-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8e08de6138043108b3b18f09d3f817a4783912e48828ab397ecf183135d84d6", size = 10998313, upload-time = "2025-07-14T20:33:24.519Z" }, - { url = "https://files.pythonhosted.org/packages/1c/c1/25b2f0d46fb7e0b5e2bee61ec3a47fe13eff9e3c2f2234f144858bbe6485/mypy-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce4a17920ec144647d448fc43725b5873548b1aae6c603225626747ededf582d", size = 10128922, upload-time = "2025-07-14T20:34:06.414Z" }, - { url = "https://files.pythonhosted.org/packages/02/78/6d646603a57aa8a2886df1b8881fe777ea60f28098790c1089230cd9c61d/mypy-1.17.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ff25d151cc057fdddb1cb1881ef36e9c41fa2a5e78d8dd71bee6e4dcd2bc05b", size = 11913524, upload-time = "2025-07-14T20:33:19.109Z" }, - { url = "https://files.pythonhosted.org/packages/4f/19/dae6c55e87ee426fb76980f7e78484450cad1c01c55a1dc4e91c930bea01/mypy-1.17.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93468cf29aa9a132bceb103bd8475f78cacde2b1b9a94fd978d50d4bdf616c9a", size = 12650527, upload-time = "2025-07-14T20:32:44.095Z" }, - { url = "https://files.pythonhosted.org/packages/86/e1/f916845a235235a6c1e4d4d065a3930113767001d491b8b2e1b61ca56647/mypy-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:98189382b310f16343151f65dd7e6867386d3e35f7878c45cfa11383d175d91f", size = 12897284, upload-time = "2025-07-14T20:33:38.168Z" }, - { url = "https://files.pythonhosted.org/packages/ae/dc/414760708a4ea1b096bd214d26a24e30ac5e917ef293bc33cdb6fe22d2da/mypy-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:c004135a300ab06a045c1c0d8e3f10215e71d7b4f5bb9a42ab80236364429937", size = 9506493, upload-time = "2025-07-14T20:34:01.093Z" }, - { url = "https://files.pythonhosted.org/packages/d4/24/82efb502b0b0f661c49aa21cfe3e1999ddf64bf5500fc03b5a1536a39d39/mypy-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d4fe5c72fd262d9c2c91c1117d16aac555e05f5beb2bae6a755274c6eec42be", size = 10914150, upload-time = "2025-07-14T20:31:51.985Z" }, - { url = "https://files.pythonhosted.org/packages/03/96/8ef9a6ff8cedadff4400e2254689ca1dc4b420b92c55255b44573de10c54/mypy-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d96b196e5c16f41b4f7736840e8455958e832871990c7ba26bf58175e357ed61", size = 10039845, upload-time = "2025-07-14T20:32:30.527Z" }, - { url = "https://files.pythonhosted.org/packages/df/32/7ce359a56be779d38021d07941cfbb099b41411d72d827230a36203dbb81/mypy-1.17.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:73a0ff2dd10337ceb521c080d4147755ee302dcde6e1a913babd59473904615f", size = 11837246, upload-time = "2025-07-14T20:32:01.28Z" }, - { url = "https://files.pythonhosted.org/packages/82/16/b775047054de4d8dbd668df9137707e54b07fe18c7923839cd1e524bf756/mypy-1.17.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24cfcc1179c4447854e9e406d3af0f77736d631ec87d31c6281ecd5025df625d", size = 12571106, upload-time = "2025-07-14T20:34:26.942Z" }, - { url = "https://files.pythonhosted.org/packages/a1/cf/fa33eaf29a606102c8d9ffa45a386a04c2203d9ad18bf4eef3e20c43ebc8/mypy-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c56f180ff6430e6373db7a1d569317675b0a451caf5fef6ce4ab365f5f2f6c3", size = 12759960, upload-time = "2025-07-14T20:33:42.882Z" }, - { url = "https://files.pythonhosted.org/packages/94/75/3f5a29209f27e739ca57e6350bc6b783a38c7621bdf9cac3ab8a08665801/mypy-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:eafaf8b9252734400f9b77df98b4eee3d2eecab16104680d51341c75702cad70", size = 9503888, upload-time = "2025-07-14T20:32:34.392Z" }, - { url = "https://files.pythonhosted.org/packages/12/e9/e6824ed620bbf51d3bf4d6cbbe4953e83eaf31a448d1b3cfb3620ccb641c/mypy-1.17.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f986f1cab8dbec39ba6e0eaa42d4d3ac6686516a5d3dccd64be095db05ebc6bb", size = 11086395, upload-time = "2025-07-14T20:34:11.452Z" }, - { url = "https://files.pythonhosted.org/packages/ba/51/a4afd1ae279707953be175d303f04a5a7bd7e28dc62463ad29c1c857927e/mypy-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:51e455a54d199dd6e931cd7ea987d061c2afbaf0960f7f66deef47c90d1b304d", size = 10120052, upload-time = "2025-07-14T20:33:09.897Z" }, - { url = "https://files.pythonhosted.org/packages/8a/71/19adfeac926ba8205f1d1466d0d360d07b46486bf64360c54cb5a2bd86a8/mypy-1.17.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3204d773bab5ff4ebbd1f8efa11b498027cd57017c003ae970f310e5b96be8d8", size = 11861806, upload-time = "2025-07-14T20:32:16.028Z" }, - { url = "https://files.pythonhosted.org/packages/0b/64/d6120eca3835baf7179e6797a0b61d6c47e0bc2324b1f6819d8428d5b9ba/mypy-1.17.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1051df7ec0886fa246a530ae917c473491e9a0ba6938cfd0ec2abc1076495c3e", size = 12744371, upload-time = "2025-07-14T20:33:33.503Z" }, - { url = "https://files.pythonhosted.org/packages/1f/dc/56f53b5255a166f5bd0f137eed960e5065f2744509dfe69474ff0ba772a5/mypy-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f773c6d14dcc108a5b141b4456b0871df638eb411a89cd1c0c001fc4a9d08fc8", size = 12914558, upload-time = "2025-07-14T20:33:56.961Z" }, - { url = "https://files.pythonhosted.org/packages/69/ac/070bad311171badc9add2910e7f89271695a25c136de24bbafc7eded56d5/mypy-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:1619a485fd0e9c959b943c7b519ed26b712de3002d7de43154a489a2d0fd817d", size = 9585447, upload-time = "2025-07-14T20:32:20.594Z" }, - { url = "https://files.pythonhosted.org/packages/be/7b/5f8ab461369b9e62157072156935cec9d272196556bdc7c2ff5f4c7c0f9b/mypy-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c41aa59211e49d717d92b3bb1238c06d387c9325d3122085113c79118bebb06", size = 11070019, upload-time = "2025-07-14T20:32:07.99Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f8/c49c9e5a2ac0badcc54beb24e774d2499748302c9568f7f09e8730e953fa/mypy-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e69db1fb65b3114f98c753e3930a00514f5b68794ba80590eb02090d54a5d4a", size = 10114457, upload-time = "2025-07-14T20:33:47.285Z" }, - { url = "https://files.pythonhosted.org/packages/89/0c/fb3f9c939ad9beed3e328008b3fb90b20fda2cddc0f7e4c20dbefefc3b33/mypy-1.17.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03ba330b76710f83d6ac500053f7727270b6b8553b0423348ffb3af6f2f7b889", size = 11857838, upload-time = "2025-07-14T20:33:14.462Z" }, - { url = "https://files.pythonhosted.org/packages/4c/66/85607ab5137d65e4f54d9797b77d5a038ef34f714929cf8ad30b03f628df/mypy-1.17.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:037bc0f0b124ce46bfde955c647f3e395c6174476a968c0f22c95a8d2f589bba", size = 12731358, upload-time = "2025-07-14T20:32:25.579Z" }, - { url = "https://files.pythonhosted.org/packages/73/d0/341dbbfb35ce53d01f8f2969facbb66486cee9804048bf6c01b048127501/mypy-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c38876106cb6132259683632b287238858bd58de267d80defb6f418e9ee50658", size = 12917480, upload-time = "2025-07-14T20:34:21.868Z" }, - { url = "https://files.pythonhosted.org/packages/64/63/70c8b7dbfc520089ac48d01367a97e8acd734f65bd07813081f508a8c94c/mypy-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:d30ba01c0f151998f367506fab31c2ac4527e6a7b2690107c7a7f9e3cb419a9c", size = 9589666, upload-time = "2025-07-14T20:34:16.841Z" }, - { url = "https://files.pythonhosted.org/packages/9f/a0/6263dd11941231f688f0a8f2faf90ceac1dc243d148d314a089d2fe25108/mypy-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:63e751f1b5ab51d6f3d219fe3a2fe4523eaa387d854ad06906c63883fde5b1ab", size = 10988185, upload-time = "2025-07-14T20:33:04.797Z" }, - { url = "https://files.pythonhosted.org/packages/02/13/b8f16d6b0dc80277129559c8e7dbc9011241a0da8f60d031edb0e6e9ac8f/mypy-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7fb09d05e0f1c329a36dcd30e27564a3555717cde87301fae4fb542402ddfad", size = 10120169, upload-time = "2025-07-14T20:32:38.84Z" }, - { url = "https://files.pythonhosted.org/packages/14/ef/978ba79df0d65af680e20d43121363cf643eb79b04bf3880d01fc8afeb6f/mypy-1.17.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b72c34ce05ac3a1361ae2ebb50757fb6e3624032d91488d93544e9f82db0ed6c", size = 11918121, upload-time = "2025-07-14T20:33:52.328Z" }, - { url = "https://files.pythonhosted.org/packages/f4/10/55ef70b104151a0d8280474f05268ff0a2a79be8d788d5e647257d121309/mypy-1.17.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:434ad499ad8dde8b2f6391ddfa982f41cb07ccda8e3c67781b1bfd4e5f9450a8", size = 12648821, upload-time = "2025-07-14T20:32:59.631Z" }, - { url = "https://files.pythonhosted.org/packages/26/8c/7781fcd2e1eef48fbedd3a422c21fe300a8e03ed5be2eb4bd10246a77f4e/mypy-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f105f61a5eff52e137fd73bee32958b2add9d9f0a856f17314018646af838e97", size = 12896955, upload-time = "2025-07-14T20:32:49.543Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/03ac759dabe86e98ca7b6681f114f90ee03f3ff8365a57049d311bd4a4e3/mypy-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:ba06254a5a22729853209550d80f94e28690d5530c661f9416a68ac097b13fc4", size = 9512957, upload-time = "2025-07-14T20:33:28.619Z" }, - { url = "https://files.pythonhosted.org/packages/e3/fc/ee058cc4316f219078464555873e99d170bde1d9569abd833300dbeb484a/mypy-1.17.0-py3-none-any.whl", hash = "sha256:15d9d0018237ab058e5de3d8fce61b6fa72cc59cc78fd91f1b474bce12abf496", size = 2283195, upload-time = "2025-07-14T20:31:54.753Z" }, -] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, -] - -[[package]] -name = "nodeenv" -version = "1.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, -] - -[[package]] -name = "packaging" -version = "25.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, -] - -[[package]] -name = "pathspec" -version = "1.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4c/b2/bb8e495d5262bfec41ab5cb18f522f1012933347fb5d9e62452d446baca2/pathspec-1.0.3.tar.gz", hash = "sha256:bac5cf97ae2c2876e2d25ebb15078eb04d76e4b98921ee31c6f85ade8b59444d", size = 130841, upload-time = "2026-01-09T15:46:46.009Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/2b/121e912bd60eebd623f873fd090de0e84f322972ab25a7f9044c056804ed/pathspec-1.0.3-py3-none-any.whl", hash = "sha256:e80767021c1cc524aa3fb14bedda9c34406591343cc42797b386ce7b9354fb6c", size = 55021, upload-time = "2026-01-09T15:46:44.652Z" }, -] - -[[package]] -name = "pluggy" -version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, -] - -[[package]] -name = "propcache" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/0e/934b541323035566a9af292dba85a195f7b78179114f2c6ebb24551118a9/propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", size = 79534, upload-time = "2025-10-08T19:46:02.083Z" }, - { url = "https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", size = 45526, upload-time = "2025-10-08T19:46:03.884Z" }, - { url = "https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", size = 47263, upload-time = "2025-10-08T19:46:05.405Z" }, - { url = "https://files.pythonhosted.org/packages/df/1b/39313ddad2bf9187a1432654c38249bab4562ef535ef07f5eb6eb04d0b1b/propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", size = 201012, upload-time = "2025-10-08T19:46:07.165Z" }, - { url = "https://files.pythonhosted.org/packages/5b/01/f1d0b57d136f294a142acf97f4ed58c8e5b974c21e543000968357115011/propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", size = 209491, upload-time = "2025-10-08T19:46:08.909Z" }, - { url = "https://files.pythonhosted.org/packages/a1/c8/038d909c61c5bb039070b3fb02ad5cccdb1dde0d714792e251cdb17c9c05/propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", size = 215319, upload-time = "2025-10-08T19:46:10.7Z" }, - { url = "https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", size = 196856, upload-time = "2025-10-08T19:46:12.003Z" }, - { url = "https://files.pythonhosted.org/packages/42/df/5615fec76aa561987a534759b3686008a288e73107faa49a8ae5795a9f7a/propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", size = 193241, upload-time = "2025-10-08T19:46:13.495Z" }, - { url = "https://files.pythonhosted.org/packages/d5/21/62949eb3a7a54afe8327011c90aca7e03547787a88fb8bd9726806482fea/propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", size = 190552, upload-time = "2025-10-08T19:46:14.938Z" }, - { url = "https://files.pythonhosted.org/packages/30/ee/ab4d727dd70806e5b4de96a798ae7ac6e4d42516f030ee60522474b6b332/propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", size = 200113, upload-time = "2025-10-08T19:46:16.695Z" }, - { url = "https://files.pythonhosted.org/packages/8a/0b/38b46208e6711b016aa8966a3ac793eee0d05c7159d8342aa27fc0bc365e/propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", size = 200778, upload-time = "2025-10-08T19:46:18.023Z" }, - { url = "https://files.pythonhosted.org/packages/cf/81/5abec54355ed344476bee711e9f04815d4b00a311ab0535599204eecc257/propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", size = 193047, upload-time = "2025-10-08T19:46:19.449Z" }, - { url = "https://files.pythonhosted.org/packages/ec/b6/1f237c04e32063cb034acd5f6ef34ef3a394f75502e72703545631ab1ef6/propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", size = 38093, upload-time = "2025-10-08T19:46:20.643Z" }, - { url = "https://files.pythonhosted.org/packages/a6/67/354aac4e0603a15f76439caf0427781bcd6797f370377f75a642133bc954/propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", size = 41638, upload-time = "2025-10-08T19:46:21.935Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e1/74e55b9fd1a4c209ff1a9a824bf6c8b3d1fc5a1ac3eabe23462637466785/propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", size = 38229, upload-time = "2025-10-08T19:46:23.368Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, - { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, - { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" }, - { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" }, - { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" }, - { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" }, - { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" }, - { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" }, - { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" }, - { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" }, - { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" }, - { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" }, - { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" }, - { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, - { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, - { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, - { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, - { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, - { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, - { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, - { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, - { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, - { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, - { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, - { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, - { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, - { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, - { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, - { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, - { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, - { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, - { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, - { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, - { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, - { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, - { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, - { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, - { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, - { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, - { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, - { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, - { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, - { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, - { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, - { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, - { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, - { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, - { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, - { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, - { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, - { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, - { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, - { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, - { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, - { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, - { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, - { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" }, - { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" }, - { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" }, - { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" }, - { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" }, - { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" }, - { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" }, - { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" }, - { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" }, - { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" }, - { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" }, - { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" }, - { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" }, - { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" }, - { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" }, - { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" }, - { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" }, - { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" }, - { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" }, - { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" }, - { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" }, - { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, - { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, - { url = "https://files.pythonhosted.org/packages/9b/01/0ebaec9003f5d619a7475165961f8e3083cf8644d704b60395df3601632d/propcache-0.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff", size = 80277, upload-time = "2025-10-08T19:48:36.647Z" }, - { url = "https://files.pythonhosted.org/packages/34/58/04af97ac586b4ef6b9026c3fd36ee7798b737a832f5d3440a4280dcebd3a/propcache-0.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb", size = 45865, upload-time = "2025-10-08T19:48:37.859Z" }, - { url = "https://files.pythonhosted.org/packages/7c/19/b65d98ae21384518b291d9939e24a8aeac4fdb5101b732576f8f7540e834/propcache-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac", size = 47636, upload-time = "2025-10-08T19:48:39.038Z" }, - { url = "https://files.pythonhosted.org/packages/b3/0f/317048c6d91c356c7154dca5af019e6effeb7ee15fa6a6db327cc19e12b4/propcache-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888", size = 201126, upload-time = "2025-10-08T19:48:40.774Z" }, - { url = "https://files.pythonhosted.org/packages/71/69/0b2a7a5a6ee83292b4b997dbd80549d8ce7d40b6397c1646c0d9495f5a85/propcache-0.4.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc", size = 209837, upload-time = "2025-10-08T19:48:42.167Z" }, - { url = "https://files.pythonhosted.org/packages/a5/92/c699ac495a6698df6e497fc2de27af4b6ace10d8e76528357ce153722e45/propcache-0.4.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a", size = 215578, upload-time = "2025-10-08T19:48:43.56Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ee/14de81c5eb02c0ee4f500b4e39c4e1bd0677c06e72379e6ab18923c773fc/propcache-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88", size = 197187, upload-time = "2025-10-08T19:48:45.309Z" }, - { url = "https://files.pythonhosted.org/packages/1d/94/48dce9aaa6d8dd5a0859bad75158ec522546d4ac23f8e2f05fac469477dd/propcache-0.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00", size = 193478, upload-time = "2025-10-08T19:48:47.743Z" }, - { url = "https://files.pythonhosted.org/packages/60/b5/0516b563e801e1ace212afde869a0596a0d7115eec0b12d296d75633fb29/propcache-0.4.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0", size = 190650, upload-time = "2025-10-08T19:48:49.373Z" }, - { url = "https://files.pythonhosted.org/packages/24/89/e0f7d4a5978cd56f8cd67735f74052f257dc471ec901694e430f0d1572fe/propcache-0.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e", size = 200251, upload-time = "2025-10-08T19:48:51.4Z" }, - { url = "https://files.pythonhosted.org/packages/06/7d/a1fac863d473876ed4406c914f2e14aa82d2f10dd207c9e16fc383cc5a24/propcache-0.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781", size = 200919, upload-time = "2025-10-08T19:48:53.227Z" }, - { url = "https://files.pythonhosted.org/packages/c3/4e/f86a256ff24944cf5743e4e6c6994e3526f6acfcfb55e21694c2424f758c/propcache-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183", size = 193211, upload-time = "2025-10-08T19:48:55.027Z" }, - { url = "https://files.pythonhosted.org/packages/6e/3f/3fbad5f4356b068f1b047d300a6ff2c66614d7030f078cd50be3fec04228/propcache-0.4.1-cp39-cp39-win32.whl", hash = "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19", size = 38314, upload-time = "2025-10-08T19:48:56.792Z" }, - { url = "https://files.pythonhosted.org/packages/a4/45/d78d136c3a3d215677abb886785aae744da2c3005bcb99e58640c56529b1/propcache-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f", size = 41912, upload-time = "2025-10-08T19:48:57.995Z" }, - { url = "https://files.pythonhosted.org/packages/fc/2a/b0632941f25139f4e58450b307242951f7c2717a5704977c6d5323a800af/propcache-0.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938", size = 38450, upload-time = "2025-10-08T19:48:59.349Z" }, - { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, -] - -[[package]] -name = "pydantic" -version = "1.10.26" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version < '3.10'", -] -dependencies = [ - { name = "typing-extensions", marker = "extra == 'group-11-dedalus-sdk-pydantic-v1'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7b/da/fd89f987a376c807cd81ea0eff4589aade783bbb702637b4734ef2c743a2/pydantic-1.10.26.tar.gz", hash = "sha256:8c6aa39b494c5af092e690127c283d84f363ac36017106a9e66cb33a22ac412e", size = 357906, upload-time = "2025-12-18T15:47:46.557Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/08/2587a6d4314e7539eec84acd062cb7b037638edb57a0335d20e4c5b8878c/pydantic-1.10.26-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f7ae36fa0ecef8d39884120f212e16c06bb096a38f523421278e2f39c1784546", size = 2444588, upload-time = "2025-12-18T15:46:28.882Z" }, - { url = "https://files.pythonhosted.org/packages/47/e6/10df5f08c105bcbb4adbee7d1108ff4b347702b110fed058f6a03f1c6b73/pydantic-1.10.26-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d95a76cf503f0f72ed7812a91de948440b2bf564269975738a4751e4fadeb572", size = 2255972, upload-time = "2025-12-18T15:46:31.72Z" }, - { url = "https://files.pythonhosted.org/packages/ba/7d/fdb961e7adc2c31f394feba6f560ef2c74c446f0285e2c2eb87d2b7206c7/pydantic-1.10.26-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a943ce8e00ad708ed06a1d9df5b4fd28f5635a003b82a4908ece6f24c0b18464", size = 2857175, upload-time = "2025-12-18T15:46:34Z" }, - { url = "https://files.pythonhosted.org/packages/8f/6c/f21e27dda475d4c562bd01b5874284dd3180f336c1e669413b743ca8b278/pydantic-1.10.26-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:465ad8edb29b15c10b779b16431fe8e77c380098badf6db367b7a1d3e572cf53", size = 2947001, upload-time = "2025-12-18T15:46:35.922Z" }, - { url = "https://files.pythonhosted.org/packages/6d/f6/27ea206232cbb6ec24dc4e4e8888a9a734f96a1eaf13504be4b30ef26aa7/pydantic-1.10.26-cp310-cp310-win_amd64.whl", hash = "sha256:80e6be6272839c8a7641d26ad569ab77772809dd78f91d0068dc0fc97f071945", size = 2066217, upload-time = "2025-12-18T15:46:37.614Z" }, - { url = "https://files.pythonhosted.org/packages/1d/c1/d521e64c8130e1ad9d22c270bed3fabcc0940c9539b076b639c88fd32a8d/pydantic-1.10.26-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:116233e53889bcc536f617e38c1b8337d7fa9c280f0fd7a4045947515a785637", size = 2428347, upload-time = "2025-12-18T15:46:39.41Z" }, - { url = "https://files.pythonhosted.org/packages/2c/08/f4b804a00c16e3ea994cb640a7c25c579b4f1fa674cde6a19fa0dfb0ae4f/pydantic-1.10.26-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c3cfdd361addb6eb64ccd26ac356ad6514cee06a61ab26b27e16b5ed53108f77", size = 2212605, upload-time = "2025-12-18T15:46:41.006Z" }, - { url = "https://files.pythonhosted.org/packages/5d/78/0df4b9efef29bbc5e39f247fcba99060d15946b4463d82a5589cf7923d71/pydantic-1.10.26-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e4451951a9a93bf9a90576f3e25240b47ee49ab5236adccb8eff6ac943adf0f", size = 2753560, upload-time = "2025-12-18T15:46:43.215Z" }, - { url = "https://files.pythonhosted.org/packages/68/66/6ab6c1d3a116d05d2508fce64f96e35242938fac07544d611e11d0d363a0/pydantic-1.10.26-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9858ed44c6bea5f29ffe95308db9e62060791c877766c67dd5f55d072c8612b5", size = 2859235, upload-time = "2025-12-18T15:46:45.112Z" }, - { url = "https://files.pythonhosted.org/packages/61/4e/f1676bb0fcdf6ed2ce4670d7d1fc1d6c3a06d84497644acfbe02649503f1/pydantic-1.10.26-cp311-cp311-win_amd64.whl", hash = "sha256:ac1089f723e2106ebde434377d31239e00870a7563245072968e5af5cc4d33df", size = 2066646, upload-time = "2025-12-18T15:46:46.816Z" }, - { url = "https://files.pythonhosted.org/packages/02/6c/cd97a5a776c4515e6ee2ae81c2f2c5be51376dda6c31f965d7746ce0019f/pydantic-1.10.26-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:468d5b9cacfcaadc76ed0a4645354ab6f263ec01a63fb6d05630ea1df6ae453f", size = 2433795, upload-time = "2025-12-18T15:46:49.321Z" }, - { url = "https://files.pythonhosted.org/packages/47/12/de20affa30dcef728fcf9cc98e13ff4438c7a630de8d2f90eb38eba0891c/pydantic-1.10.26-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2c1b0b914be31671000ca25cf7ea17fcaaa68cfeadf6924529c5c5aa24b7ab1f", size = 2227387, upload-time = "2025-12-18T15:46:50.877Z" }, - { url = "https://files.pythonhosted.org/packages/7b/1d/9d65dcc5b8c17ba590f1f9f486e9306346831902318b7ee93f63516f4003/pydantic-1.10.26-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15b13b9f8ba8867095769e1156e0d7fbafa1f65b898dd40fd1c02e34430973cb", size = 2629594, upload-time = "2025-12-18T15:46:53.42Z" }, - { url = "https://files.pythonhosted.org/packages/3f/76/acb41409356789e23e1a7ef58f93821410c96409183ce314ddb58d97f23e/pydantic-1.10.26-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad7025ca324ae263d4313998e25078dcaec5f9ed0392c06dedb57e053cc8086b", size = 2745305, upload-time = "2025-12-18T15:46:55.987Z" }, - { url = "https://files.pythonhosted.org/packages/22/72/a98c0c5e527a66057d969fedd61675223c7975ade61acebbca9f1abd6dc0/pydantic-1.10.26-cp312-cp312-win_amd64.whl", hash = "sha256:4482b299874dabb88a6c3759e3d85c6557c407c3b586891f7d808d8a38b66b9c", size = 1937647, upload-time = "2025-12-18T15:46:57.905Z" }, - { url = "https://files.pythonhosted.org/packages/28/b9/17a5a5a421c23ac27486b977724a42c9d5f8b7f0f4aab054251066223900/pydantic-1.10.26-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1ae7913bb40a96c87e3d3f6fe4e918ef53bf181583de4e71824360a9b11aef1c", size = 2494599, upload-time = "2025-12-18T15:47:00.209Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8e/6e3bd4241076cf227b443d7577245dd5d181ecf40b3182fcb908bc8c197d/pydantic-1.10.26-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8154c13f58d4de5d3a856bb6c909c7370f41fb876a5952a503af6b975265f4ba", size = 2254391, upload-time = "2025-12-18T15:47:02.268Z" }, - { url = "https://files.pythonhosted.org/packages/a8/30/a1c4092eda2145ecbead6c92db489b223e101e1ba0da82576d0cf73dd422/pydantic-1.10.26-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f8af0507bf6118b054a9765fb2e402f18a8b70c964f420d95b525eb711122d62", size = 2609445, upload-time = "2025-12-18T15:47:04.909Z" }, - { url = "https://files.pythonhosted.org/packages/3a/2a/0491f1729ee4b7b6bc859ec22f69752f0c09bee1b66ac6f5f701136f34c3/pydantic-1.10.26-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dcb5a7318fb43189fde6af6f21ac7149c4bcbcfffc54bc87b5becddc46084847", size = 2732124, upload-time = "2025-12-18T15:47:07.464Z" }, - { url = "https://files.pythonhosted.org/packages/2a/56/b59f3b2f84e1df2b04ae768a1bb04d9f0288ff71b67cdcbb07683757b2c0/pydantic-1.10.26-cp313-cp313-win_amd64.whl", hash = "sha256:71cde228bc0600cf8619f0ee62db050d1880dcc477eba0e90b23011b4ee0f314", size = 1939888, upload-time = "2025-12-18T15:47:09.618Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/0c3dc02d4b97790b0f199bf933f677c14e7be4a8d21307c5f2daae06aa41/pydantic-1.10.26-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6b40730cc81d53d515dc0b8bb5c9b43fadb9bed46de4a3c03bd95e8571616dba", size = 2502689, upload-time = "2025-12-18T15:47:12.308Z" }, - { url = "https://files.pythonhosted.org/packages/d4/9d/d31aeea45542b2ae4b09ecba92b88aaba696b801c31919811aa979a1242d/pydantic-1.10.26-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c3bbb9c0eecdf599e4db9b372fa9cc55be12e80a0d9c6d307950a39050cb0e37", size = 2269494, upload-time = "2025-12-18T15:47:14.53Z" }, - { url = "https://files.pythonhosted.org/packages/78/c1/3a4d069593283ca4dd0006039ba33644e21e432cddc09da706ac50441610/pydantic-1.10.26-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc2e3fe7bc4993626ef6b6fa855defafa1d6f8996aa1caef2deb83c5ac4d043a", size = 2620047, upload-time = "2025-12-18T15:47:17.089Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0e/340c3d29197d99c15ab04093d43bb9c9d0fd17c2a34b80cb9d36ed732b09/pydantic-1.10.26-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:36d9e46b588aaeb1dcd2409fa4c467fe0b331f3cc9f227b03a7a00643704e962", size = 2747625, upload-time = "2025-12-18T15:47:19.21Z" }, - { url = "https://files.pythonhosted.org/packages/1e/58/f12ab3727339b172c830b32151919456b67787cdfe8808b2568b322fb15c/pydantic-1.10.26-cp314-cp314-win_amd64.whl", hash = "sha256:81ce3c8616d12a7be31b4aadfd3434f78f6b44b75adbfaec2fe1ad4f7f999b8c", size = 1976436, upload-time = "2025-12-18T15:47:21.384Z" }, - { url = "https://files.pythonhosted.org/packages/e1/8a/3a5a6267d5f03617b5c0f1985aa9fdfbafd33a50ef6dadd866a15ed4d123/pydantic-1.10.26-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:502b9d30d18a2dfaf81b7302f6ba0e5853474b1c96212449eb4db912cb604b7d", size = 2457039, upload-time = "2025-12-18T15:47:34.584Z" }, - { url = "https://files.pythonhosted.org/packages/f3/fa/343ac0db26918a033ac6256c036d72c3b6eb1196b7de622e2e8a94b19079/pydantic-1.10.26-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0d8f6087bf697dec3bf7ffcd7fe8362674f16519f3151789f33cbe8f1d19fc15", size = 2266441, upload-time = "2025-12-18T15:47:36.807Z" }, - { url = "https://files.pythonhosted.org/packages/fc/36/1ab48136578608dba2f2a62e452f3db2083b474d4e49be5749c6ae0c123c/pydantic-1.10.26-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dd40a99c358419910c85e6f5d22f9c56684c25b5e7abc40879b3b4a52f34ae90", size = 2869383, upload-time = "2025-12-18T15:47:38.883Z" }, - { url = "https://files.pythonhosted.org/packages/a2/25/41dbf1bffc31eb242cece8080561a4133eaeb513372dec36a84477a3fb71/pydantic-1.10.26-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ce3293b86ca9f4125df02ff0a70be91bc7946522467cbd98e7f1493f340616ba", size = 2963582, upload-time = "2025-12-18T15:47:40.854Z" }, - { url = "https://files.pythonhosted.org/packages/61/2f/f072ae160a300c85eb9f059915101fd33dacf12d8df08c2b804acb3b95d1/pydantic-1.10.26-cp39-cp39-win_amd64.whl", hash = "sha256:1a4e3062b71ab1d5df339ba12c48f9ed5817c5de6cb92a961dd5c64bb32e7b96", size = 2075530, upload-time = "2025-12-18T15:47:43.181Z" }, - { url = "https://files.pythonhosted.org/packages/1f/98/556e82f00b98486def0b8af85da95e69d2be7e367cf2431408e108bc3095/pydantic-1.10.26-py3-none-any.whl", hash = "sha256:c43ad70dc3ce7787543d563792426a16fd7895e14be4b194b5665e36459dd917", size = 166975, upload-time = "2025-12-18T15:47:44.927Z" }, -] - -[[package]] -name = "pydantic" -version = "2.12.5" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version < '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version < '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", -] -dependencies = [ - { name = "annotated-types", marker = "extra == 'group-11-dedalus-sdk-pydantic-v2' or extra != 'group-11-dedalus-sdk-pydantic-v1'" }, - { name = "pydantic-core", marker = "extra == 'group-11-dedalus-sdk-pydantic-v2' or extra != 'group-11-dedalus-sdk-pydantic-v1'" }, - { name = "typing-extensions", marker = "extra == 'group-11-dedalus-sdk-pydantic-v2' or extra != 'group-11-dedalus-sdk-pydantic-v1'" }, - { name = "typing-inspection", marker = "extra == 'group-11-dedalus-sdk-pydantic-v2' or extra != 'group-11-dedalus-sdk-pydantic-v1'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, -] - -[[package]] -name = "pydantic-core" -version = "2.41.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "extra == 'group-11-dedalus-sdk-pydantic-v2' or extra != 'group-11-dedalus-sdk-pydantic-v1'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, - { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, - { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, - { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, - { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, - { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, - { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, - { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, - { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, - { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, - { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, - { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, - { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, - { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, - { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, - { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, - { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, - { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, - { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, - { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, - { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, - { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, - { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, - { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, - { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, - { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, - { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, - { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, - { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, - { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, - { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, - { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, - { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, - { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, - { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, - { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, - { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, - { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, - { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, - { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, - { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, - { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, - { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, - { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, - { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, - { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, - { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, - { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, - { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, - { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, - { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, - { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, - { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, - { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, - { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, - { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, - { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, - { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, - { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, - { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/54/db/160dffb57ed9a3705c4cbcbff0ac03bdae45f1ca7d58ab74645550df3fbd/pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf", size = 2107999, upload-time = "2025-11-04T13:42:03.885Z" }, - { url = "https://files.pythonhosted.org/packages/a3/7d/88e7de946f60d9263cc84819f32513520b85c0f8322f9b8f6e4afc938383/pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5", size = 1929745, upload-time = "2025-11-04T13:42:06.075Z" }, - { url = "https://files.pythonhosted.org/packages/d5/c2/aef51e5b283780e85e99ff19db0f05842d2d4a8a8cd15e63b0280029b08f/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d", size = 1920220, upload-time = "2025-11-04T13:42:08.457Z" }, - { url = "https://files.pythonhosted.org/packages/c7/97/492ab10f9ac8695cd76b2fdb24e9e61f394051df71594e9bcc891c9f586e/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60", size = 2067296, upload-time = "2025-11-04T13:42:10.817Z" }, - { url = "https://files.pythonhosted.org/packages/ec/23/984149650e5269c59a2a4c41d234a9570adc68ab29981825cfaf4cfad8f4/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82", size = 2231548, upload-time = "2025-11-04T13:42:13.843Z" }, - { url = "https://files.pythonhosted.org/packages/71/0c/85bcbb885b9732c28bec67a222dbed5ed2d77baee1f8bba2002e8cd00c5c/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5", size = 2362571, upload-time = "2025-11-04T13:42:16.208Z" }, - { url = "https://files.pythonhosted.org/packages/c0/4a/412d2048be12c334003e9b823a3fa3d038e46cc2d64dd8aab50b31b65499/pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3", size = 2068175, upload-time = "2025-11-04T13:42:18.911Z" }, - { url = "https://files.pythonhosted.org/packages/73/f4/c58b6a776b502d0a5540ad02e232514285513572060f0d78f7832ca3c98b/pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425", size = 2177203, upload-time = "2025-11-04T13:42:22.578Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ae/f06ea4c7e7a9eead3d165e7623cd2ea0cb788e277e4f935af63fc98fa4e6/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504", size = 2148191, upload-time = "2025-11-04T13:42:24.89Z" }, - { url = "https://files.pythonhosted.org/packages/c1/57/25a11dcdc656bf5f8b05902c3c2934ac3ea296257cc4a3f79a6319e61856/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5", size = 2343907, upload-time = "2025-11-04T13:42:27.683Z" }, - { url = "https://files.pythonhosted.org/packages/96/82/e33d5f4933d7a03327c0c43c65d575e5919d4974ffc026bc917a5f7b9f61/pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3", size = 2322174, upload-time = "2025-11-04T13:42:30.776Z" }, - { url = "https://files.pythonhosted.org/packages/81/45/4091be67ce9f469e81656f880f3506f6a5624121ec5eb3eab37d7581897d/pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460", size = 1990353, upload-time = "2025-11-04T13:42:33.111Z" }, - { url = "https://files.pythonhosted.org/packages/44/8a/a98aede18db6e9cd5d66bcacd8a409fcf8134204cdede2e7de35c5a2c5ef/pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b", size = 2015698, upload-time = "2025-11-04T13:42:35.484Z" }, - { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, - { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, - { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, - { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, - { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, - { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, - { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, - { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, - { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, - { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, - { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, - { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, - { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, - { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, - { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, - { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, - { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, - { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, -] - -[[package]] -name = "pygments" -version = "2.19.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, -] - -[[package]] -name = "pyright" -version = "1.1.399" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "nodeenv" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/db/9d/d91d5f6d26b2db95476fefc772e2b9a16d54c6bd0ea6bb5c1b6d635ab8b4/pyright-1.1.399.tar.gz", hash = "sha256:439035d707a36c3d1b443aec980bc37053fbda88158eded24b8eedcf1c7b7a1b", size = 3856954, upload-time = "2025-04-10T04:40:25.703Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/b5/380380c9e7a534cb1783c70c3e8ac6d1193c599650a55838d0557586796e/pyright-1.1.399-py3-none-any.whl", hash = "sha256:55f9a875ddf23c9698f24208c764465ffdfd38be6265f7faf9a176e1dc549f3b", size = 5592584, upload-time = "2025-04-10T04:40:23.502Z" }, -] - -[[package]] -name = "pytest" -version = "8.4.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "colorama", marker = "(python_full_version < '3.10' and sys_platform == 'win32') or (python_full_version >= '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2') or (sys_platform != 'win32' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "exceptiongroup", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "packaging", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pluggy", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pygments", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "tomli", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, -] - -[[package]] -name = "pytest" -version = "9.0.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", -] -dependencies = [ - { name = "colorama", marker = "(python_full_version >= '3.10' and sys_platform == 'win32') or (python_full_version < '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2') or (sys_platform != 'win32' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "exceptiongroup", marker = "python_full_version == '3.10.*' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "packaging", marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pluggy", marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pygments", marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "tomli", marker = "python_full_version == '3.10.*' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, -] - -[[package]] -name = "pytest-asyncio" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "backports-asyncio-runner", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "typing-extensions", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/86/9e3c5f48f7b7b638b216e4b9e645f54d199d7abbbab7a64a13b4e12ba10f/pytest_asyncio-1.2.0.tar.gz", hash = "sha256:c609a64a2a8768462d0c99811ddb8bd2583c33fd33cf7f21af1c142e824ffb57", size = 50119, upload-time = "2025-09-12T07:33:53.816Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl", hash = "sha256:8e17ae5e46d8e7efe51ab6494dd2010f4ca8dae51652aa3c8d55acf50bfb2e99", size = 15095, upload-time = "2025-09-12T07:33:52.639Z" }, -] - -[[package]] -name = "pytest-asyncio" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", -] -dependencies = [ - { name = "backports-asyncio-runner", marker = "python_full_version == '3.10.*' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" }, -] - -[[package]] -name = "pytest-xdist" -version = "3.8.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "execnet" }, - { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, -] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, -] - -[[package]] -name = "respx" -version = "0.22.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "httpx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f4/7c/96bd0bc759cf009675ad1ee1f96535edcb11e9666b985717eb8c87192a95/respx-0.22.0.tar.gz", hash = "sha256:3c8924caa2a50bd71aefc07aa812f2466ff489f1848c96e954a5362d17095d91", size = 28439, upload-time = "2024-12-19T22:33:59.374Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/67/afbb0978d5399bc9ea200f1d4489a23c9a1dad4eee6376242b8182389c79/respx-0.22.0-py2.py3-none-any.whl", hash = "sha256:631128d4c9aba15e56903fb5f66fb1eff412ce28dd387ca3a81339e52dbd3ad0", size = 25127, upload-time = "2024-12-19T22:33:57.837Z" }, -] - -[[package]] -name = "rich" -version = "14.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, -] - -[[package]] -name = "ruff" -version = "0.14.13" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" }, - { url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" }, - { url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" }, - { url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" }, - { url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" }, - { url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" }, - { url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" }, - { url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" }, - { url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" }, - { url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" }, - { url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" }, - { url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" }, - { url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" }, - { url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" }, - { url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" }, - { url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" }, -] - -[[package]] -name = "six" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, -] - -[[package]] -name = "time-machine" -version = "2.19.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "python-dateutil", marker = "python_full_version < '3.10' or (extra == 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/1b5fdd165f61b67f445fac2a7feb0c655118edef429cd09ff5a8067f7f1d/time_machine-2.19.0.tar.gz", hash = "sha256:7c5065a8b3f2bbb449422c66ef71d114d3f909c276a6469642ecfffb6a0fcd29", size = 14576, upload-time = "2025-08-19T17:22:08.402Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/8f/19125611ebbcb3a14da14cd982b9eb4573e2733db60c9f1fbf6a39534f40/time_machine-2.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b5169018ef47206997b46086ce01881cd3a4666fd2998c9d76a87858ca3e49e9", size = 19659, upload-time = "2025-08-19T17:20:30.062Z" }, - { url = "https://files.pythonhosted.org/packages/74/da/9b0a928321e7822a3ff96dbd1eae089883848e30e9e1b149b85fb96ba56b/time_machine-2.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:85bb7ed440fccf6f6d0c8f7d68d849e7c3d1f771d5e0b2cdf871fa6561da569f", size = 15157, upload-time = "2025-08-19T17:20:31.931Z" }, - { url = "https://files.pythonhosted.org/packages/36/ff/d7e943422038f5f2161fe2c2d791e64a45be691ef946020b20f3a6efc4d4/time_machine-2.19.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a3b12028af1cdc09ccd595be2168b7b26f206c1e190090b048598fbe278beb8e", size = 32860, upload-time = "2025-08-19T17:20:33.241Z" }, - { url = "https://files.pythonhosted.org/packages/fc/80/2b0f1070ed9808ee7da7a6da62a4a0b776957cb4d861578348f86446e778/time_machine-2.19.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c261f073086cf081d1443cbf7684148c662659d3d139d06b772bfe3fe7cc71a6", size = 34510, upload-time = "2025-08-19T17:20:34.221Z" }, - { url = "https://files.pythonhosted.org/packages/ef/b4/48038691c8d89924b36c83335a73adeeb68c884f5a1da08a5b17b8a956f3/time_machine-2.19.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:011954d951230a9f1079f22b39ed1a3a9abb50ee297dfb8c557c46351659d94d", size = 36204, upload-time = "2025-08-19T17:20:35.163Z" }, - { url = "https://files.pythonhosted.org/packages/37/2e/60e8adb541df195e83cb74b720b2cfb1f22ed99c5a7f8abf2a9ab3442cb5/time_machine-2.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b0f83308b29c7872006803f2e77318874eb84d0654f2afe0e48e3822e7a2e39b", size = 34936, upload-time = "2025-08-19T17:20:36.61Z" }, - { url = "https://files.pythonhosted.org/packages/5e/72/e8cee59c6cd99dd3b25b8001a0253e779a286aa8f44d5b40777cbd66210b/time_machine-2.19.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:39733ef844e2984620ec9382a42d00cccc4757d75a5dd572be8c2572e86e50b9", size = 32932, upload-time = "2025-08-19T17:20:37.901Z" }, - { url = "https://files.pythonhosted.org/packages/2c/eb/83f300d93c1504965d944e03679f1c943a923bce2d0fdfadef0e2e22cc13/time_machine-2.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f8db99f6334432e9ffbf00c215caf2ae9773f17cec08304d77e9e90febc3507b", size = 34010, upload-time = "2025-08-19T17:20:39.202Z" }, - { url = "https://files.pythonhosted.org/packages/e1/77/f35f2500e04daac5033a22fbfd17e68467822b8406ee77966bf222ccaa26/time_machine-2.19.0-cp310-cp310-win32.whl", hash = "sha256:72bf66cd19e27ffd26516b9cbe676d50c2e0b026153289765dfe0cf406708128", size = 17121, upload-time = "2025-08-19T17:20:40.108Z" }, - { url = "https://files.pythonhosted.org/packages/db/df/32d3e0404be1760a64a44caab2af34b07e952bfe00a23134fea9ddba3e8a/time_machine-2.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:46f1c945934ce3d6b4f388b8e581fce7f87ec891ea90d7128e19520e434f96f0", size = 17957, upload-time = "2025-08-19T17:20:41.079Z" }, - { url = "https://files.pythonhosted.org/packages/66/df/598a71a1afb4b509a4587273b76590b16d9110a3e9106f01eedc68d02bb2/time_machine-2.19.0-cp310-cp310-win_arm64.whl", hash = "sha256:fb4897c7a5120a4fd03f0670f332d83b7e55645886cd8864a71944c4c2e5b35b", size = 16821, upload-time = "2025-08-19T17:20:41.967Z" }, - { url = "https://files.pythonhosted.org/packages/1d/ed/4815ebcc9b6c14273f692b9be38a9b09eae52a7e532407cc61a51912b121/time_machine-2.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5ee91664880434d98e41585c3446dac7180ec408c786347451ddfca110d19296", size = 19342, upload-time = "2025-08-19T17:20:43.207Z" }, - { url = "https://files.pythonhosted.org/packages/ee/08/154cce8b11b60d8238b0b751b8901d369999f4e8f7c3a5f917caa5d95b0b/time_machine-2.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed3732b83a893d1c7b8cabde762968b4dc5680ee0d305b3ecca9bb516f4e3862", size = 14978, upload-time = "2025-08-19T17:20:44.134Z" }, - { url = "https://files.pythonhosted.org/packages/c7/b7/b689d8c8eeca7af375cfcd64973e49e83aa817cc00f80f98548d42c0eb50/time_machine-2.19.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6ba0303e9cc9f7f947e344f501e26bedfb68fab521e3c2729d370f4f332d2d55", size = 30964, upload-time = "2025-08-19T17:20:45.366Z" }, - { url = "https://files.pythonhosted.org/packages/80/91/38bf9c79674e95ce32e23c267055f281dff651eec77ed32a677db3dc011a/time_machine-2.19.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2851825b524a988ee459c37c1c26bdfaa7eff78194efb2b562ea497a6f375b0a", size = 32606, upload-time = "2025-08-19T17:20:46.693Z" }, - { url = "https://files.pythonhosted.org/packages/19/4a/e9222d85d4de68975a5e799f539a9d32f3a134a9101fca0a61fa6aa33d68/time_machine-2.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:68d32b09ecfd7fef59255c091e8e7c24dd117f882c4880b5c7ab8c5c32a98f89", size = 34405, upload-time = "2025-08-19T17:20:48.032Z" }, - { url = "https://files.pythonhosted.org/packages/14/e2/09480d608d42d6876f9ff74593cfc9197a7eb2c31381a74fb2b145575b65/time_machine-2.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60c46ab527bf2fa144b530f639cc9e12803524c9e1f111dc8c8f493bb6586eeb", size = 33181, upload-time = "2025-08-19T17:20:48.937Z" }, - { url = "https://files.pythonhosted.org/packages/84/64/f9359e000fad32d9066305c48abc527241d608bcdf77c19d67d66e268455/time_machine-2.19.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:56f26ab9f0201c453d18fe76bb7d1cf05fe58c1b9d9cb0c7d243d05132e01292", size = 31036, upload-time = "2025-08-19T17:20:50.276Z" }, - { url = "https://files.pythonhosted.org/packages/71/0d/fab2aacec71e3e482bd7fce0589381f9414a4a97f8766bddad04ad047b7b/time_machine-2.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6c806cf3c1185baa1d807b7f51bed0db7a6506832c961d5d1b4c94c775749bc0", size = 32145, upload-time = "2025-08-19T17:20:51.449Z" }, - { url = "https://files.pythonhosted.org/packages/44/fb/faeba2405fb27553f7b28db441a500e2064ffdb2dcba001ee315fdd2c121/time_machine-2.19.0-cp311-cp311-win32.whl", hash = "sha256:b30039dfd89855c12138095bee39c540b4633cbc3684580d684ef67a99a91587", size = 17004, upload-time = "2025-08-19T17:20:52.38Z" }, - { url = "https://files.pythonhosted.org/packages/2f/84/87e483d660ca669426192969280366635c845c3154a9fe750be546ed3afc/time_machine-2.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:13ed8b34430f1de79905877f5600adffa626793ab4546a70a99fb72c6a3350d8", size = 17822, upload-time = "2025-08-19T17:20:53.348Z" }, - { url = "https://files.pythonhosted.org/packages/41/f4/ebf7bbf5047854a528adaf54a5e8780bc5f7f0104c298ab44566a3053bf8/time_machine-2.19.0-cp311-cp311-win_arm64.whl", hash = "sha256:cc29a50a0257d8750b08056b66d7225daab47606832dea1a69e8b017323bf511", size = 16680, upload-time = "2025-08-19T17:20:54.26Z" }, - { url = "https://files.pythonhosted.org/packages/9b/aa/7e00614d339e4d687f6e96e312a1566022528427d237ec639df66c4547bc/time_machine-2.19.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c85cf437dc3c07429456d8d6670ac90ecbd8241dcd0fbf03e8db2800576f91ff", size = 19308, upload-time = "2025-08-19T17:20:55.25Z" }, - { url = "https://files.pythonhosted.org/packages/ab/3c/bde3c757394f5bca2fbc1528d4117960a26c38f9b160bf471b38d2378d8f/time_machine-2.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d9238897e8ef54acdf59f5dff16f59ca0720e7c02d820c56b4397c11db5d3eb9", size = 15019, upload-time = "2025-08-19T17:20:56.204Z" }, - { url = "https://files.pythonhosted.org/packages/c8/e0/8ca916dd918018352d377f1f5226ee071cfbeb7dbbde2b03d14a411ac2b1/time_machine-2.19.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e312c7d5d6bfffb96c6a7b39ff29e3046de100d7efaa3c01552654cfbd08f14c", size = 33079, upload-time = "2025-08-19T17:20:57.166Z" }, - { url = "https://files.pythonhosted.org/packages/48/69/184a0209f02dd0cb5e01e8d13cd4c97a5f389c4e3d09b95160dd676ad1e7/time_machine-2.19.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:714c40b2c90d1c57cc403382d5a9cf16e504cb525bfe9650095317da3c3d62b5", size = 34925, upload-time = "2025-08-19T17:20:58.117Z" }, - { url = "https://files.pythonhosted.org/packages/43/42/4bbf4309e8e57cea1086eb99052d97ff6ddecc1ab6a3b07aa4512f8bf963/time_machine-2.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2eaa1c675d500dc3ccae19e9fb1feff84458a68c132bbea47a80cc3dd2df7072", size = 36384, upload-time = "2025-08-19T17:20:59.108Z" }, - { url = "https://files.pythonhosted.org/packages/b1/af/9f510dc1719157348c1a2e87423aed406589070b54b503cb237d9bf3a4fe/time_machine-2.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e77a414e9597988af53b2b2e67242c9d2f409769df0d264b6d06fda8ca3360d4", size = 34881, upload-time = "2025-08-19T17:21:00.116Z" }, - { url = "https://files.pythonhosted.org/packages/ca/28/61764a635c70cc76c76ba582dfdc1a84834cddaeb96789023af5214426b2/time_machine-2.19.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cd93996970e11c382b04d4937c3cd0b0167adeef14725ece35aae88d8a01733c", size = 32931, upload-time = "2025-08-19T17:21:01.095Z" }, - { url = "https://files.pythonhosted.org/packages/b6/e0/f028d93b266e6ade8aca5851f76ebbc605b2905cdc29981a2943b43e1a6c/time_machine-2.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8e20a6d8d6e23174bd7e931e134d9610b136db460b249d07e84ecdad029ec352", size = 34241, upload-time = "2025-08-19T17:21:02.052Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a6/36d1950ed1d3f613158024cf1dcc73db1d9ef0b9117cf51ef2e37dc06499/time_machine-2.19.0-cp312-cp312-win32.whl", hash = "sha256:95afc9bc65228b27be80c2756799c20b8eb97c4ef382a9b762b6d7888bc84099", size = 17021, upload-time = "2025-08-19T17:21:03.374Z" }, - { url = "https://files.pythonhosted.org/packages/b1/0d/e2dce93355abda3cac69e77fe96566757e98b8fe7fdcbddce89c9ced3f5f/time_machine-2.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:e84909af950e2448f4e2562ea5759c946248c99ab380d2b47d79b62bd76fa236", size = 17857, upload-time = "2025-08-19T17:21:04.331Z" }, - { url = "https://files.pythonhosted.org/packages/eb/28/50ae6fb83b7feeeca7a461c0dc156cf7ef5e6ef594a600d06634fde6a2cb/time_machine-2.19.0-cp312-cp312-win_arm64.whl", hash = "sha256:0390a1ea9fa7e9d772a39b7c61b34fdcca80eb9ffac339cc0441c6c714c81470", size = 16677, upload-time = "2025-08-19T17:21:05.39Z" }, - { url = "https://files.pythonhosted.org/packages/a9/b8/24ebce67aa531bae2cbe164bb3f4abc6467dc31f3aead35e77f5a075ea3e/time_machine-2.19.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5e172866753e6041d3b29f3037dc47c20525176a494a71bbd0998dfdc4f11f2f", size = 19373, upload-time = "2025-08-19T17:21:06.701Z" }, - { url = "https://files.pythonhosted.org/packages/53/a5/c9a5240fd2f845d3ff9fa26f8c8eaa29f7239af9d65007e61d212250f15b/time_machine-2.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f70f68379bd6f542ae6775cce9a4fa3dcc20bf7959c42eaef871c14469e18097", size = 15056, upload-time = "2025-08-19T17:21:07.667Z" }, - { url = "https://files.pythonhosted.org/packages/b9/92/66cce5d2fb2a5e68459aca85fd18a7e2d216f725988940cd83f96630f2f1/time_machine-2.19.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e69e0b0f694728a00e72891ef8dd00c7542952cb1c87237db594b6b27d504a96", size = 33172, upload-time = "2025-08-19T17:21:08.619Z" }, - { url = "https://files.pythonhosted.org/packages/ae/20/b499e9ab4364cd466016c33dcdf4f56629ca4c20b865bd4196d229f31d92/time_machine-2.19.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3ae0a8b869574301ec5637e32c270c7384cca5cd6e230f07af9d29271a7fa293", size = 35042, upload-time = "2025-08-19T17:21:09.622Z" }, - { url = "https://files.pythonhosted.org/packages/41/32/b252d3d32791eb16c07d553c820dbc33d9c7fa771de3d1c602190bded2b7/time_machine-2.19.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:554e4317de90e2f7605ff80d153c8bb56b38c0d0c0279feb17e799521e987b8c", size = 36535, upload-time = "2025-08-19T17:21:10.571Z" }, - { url = "https://files.pythonhosted.org/packages/98/cf/4d0470062b9742e1b040ab81bad04d1a5d1de09806507bb6188989cfa1a7/time_machine-2.19.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6567a5ec5538ed550539ac29be11b3cb36af1f9894e2a72940cba0292cc7c3c9", size = 34945, upload-time = "2025-08-19T17:21:11.538Z" }, - { url = "https://files.pythonhosted.org/packages/24/71/2f741b29d98b1c18f6777a32236497c3d3264b6077e431cea4695684c8a1/time_machine-2.19.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82e9ffe8dfff07b0d810a2ad015a82cd78c6a237f6c7cf185fa7f747a3256f8a", size = 33014, upload-time = "2025-08-19T17:21:12.858Z" }, - { url = "https://files.pythonhosted.org/packages/e8/83/ca8dba6106562843fd99f672e5aaf95badbc10f4f13f7cfe8d8640a7019d/time_machine-2.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7e1c4e578cdd69b3531d8dd3fbcb92a0cd879dadb912ee37af99c3a9e3c0d285", size = 34350, upload-time = "2025-08-19T17:21:13.923Z" }, - { url = "https://files.pythonhosted.org/packages/21/7f/34fe540450e18d0a993240100e4b86e8d03d831b92af8bb6ddb2662dc6fc/time_machine-2.19.0-cp313-cp313-win32.whl", hash = "sha256:72dbd4cbc3d96dec9dd281ddfbb513982102776b63e4e039f83afb244802a9e5", size = 17047, upload-time = "2025-08-19T17:21:14.874Z" }, - { url = "https://files.pythonhosted.org/packages/bf/5d/c8be73df82c7ebe7cd133279670e89b8b110af3ce1412c551caa9d08e625/time_machine-2.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:e17e3e089ac95f9a145ce07ff615e3c85674f7de36f2d92aaf588493a23ffb4b", size = 17868, upload-time = "2025-08-19T17:21:15.819Z" }, - { url = "https://files.pythonhosted.org/packages/92/13/2dfd3b8fb285308f61cd7aa9bfa96f46ddf916e3549a0f0afd094c556599/time_machine-2.19.0-cp313-cp313-win_arm64.whl", hash = "sha256:149072aff8e3690e14f4916103d898ea0d5d9c95531b6aa0995251c299533f7b", size = 16710, upload-time = "2025-08-19T17:21:16.748Z" }, - { url = "https://files.pythonhosted.org/packages/05/c1/deebb361727d2c5790f9d4d874be1b19afd41f4375581df465e6718b46a2/time_machine-2.19.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f3589fee1ed0ab6ee424a55b0ea1ec694c4ba64cc26895bcd7d99f3d1bc6a28a", size = 20053, upload-time = "2025-08-19T17:21:17.704Z" }, - { url = "https://files.pythonhosted.org/packages/45/e8/fe3376951e6118d8ec1d1f94066a169b791424fe4a26c7dfc069b153ee08/time_machine-2.19.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7887e85275c4975fe54df03dcdd5f38bd36be973adc68a8c77e17441c3b443d6", size = 15423, upload-time = "2025-08-19T17:21:18.668Z" }, - { url = "https://files.pythonhosted.org/packages/9c/c7/f88d95cd1a87c650cf3749b4d64afdaf580297aa18ad7f4b44ec9d252dfc/time_machine-2.19.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ce0be294c209928563fcce1c587963e60ec803436cf1e181acd5bc1e425d554b", size = 39630, upload-time = "2025-08-19T17:21:19.645Z" }, - { url = "https://files.pythonhosted.org/packages/cc/5d/65a5c48a65357e56ec6f032972e4abd1c02d4fca4b0717a3aaefd19014d4/time_machine-2.19.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a62fd1ab380012c86f4c042010418ed45eb31604f4bf4453e17c9fa60bc56a29", size = 41242, upload-time = "2025-08-19T17:21:20.979Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f9/fe5209e1615fde0a8cad6c4e857157b150333ed1fe31a7632b08cfe0ebdd/time_machine-2.19.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b25ec853a4530a5800731257f93206b12cbdee85ede964ebf8011b66086a7914", size = 44278, upload-time = "2025-08-19T17:21:21.984Z" }, - { url = "https://files.pythonhosted.org/packages/4a/3a/a5e5fe9c5d614cde0a9387ff35e8dfd12c5ef6384e4c1a21b04e6e0b905d/time_machine-2.19.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a430e4d0e0556f021a9c78e9b9f68e5e8910bdace4aa34ed4d1a73e239ed9384", size = 42321, upload-time = "2025-08-19T17:21:23.755Z" }, - { url = "https://files.pythonhosted.org/packages/a1/c5/56eca774e9162bc1ce59111d2bd69140dc8908c9478c92ec7bd15d547600/time_machine-2.19.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2415b7495ec4364c8067071e964fbadfe746dd4cdb43983f2f0bd6ebed13315c", size = 39270, upload-time = "2025-08-19T17:21:26.009Z" }, - { url = "https://files.pythonhosted.org/packages/9b/69/5dd0c420667578169a12acc8c8fd7452e8cfb181e41c9b4ac7e88fa36686/time_machine-2.19.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dbfc6b90c10f288594e1bf89a728a98cc0030791fd73541bbdc6b090aff83143", size = 40193, upload-time = "2025-08-19T17:21:27.054Z" }, - { url = "https://files.pythonhosted.org/packages/75/a7/de974d421bd55c9355583427c2a38fb0237bb5fd6614af492ba89dacb2f9/time_machine-2.19.0-cp313-cp313t-win32.whl", hash = "sha256:16f5d81f650c0a4d117ab08036dc30b5f8b262e11a4a0becc458e7f1c011b228", size = 17542, upload-time = "2025-08-19T17:21:28.674Z" }, - { url = "https://files.pythonhosted.org/packages/76/0a/aa0d05becd5d06ae8d3f16d657dc8cc9400c8d79aef80299de196467ff12/time_machine-2.19.0-cp313-cp313t-win_amd64.whl", hash = "sha256:645699616ec14e147094f601e6ab9553ff6cea37fad9c42720a6d7ed04bcd5dc", size = 18703, upload-time = "2025-08-19T17:21:29.663Z" }, - { url = "https://files.pythonhosted.org/packages/1f/c0/f785a4c7c73aa176510f7c48b84b49c26be84af0d534deb222e0327f750e/time_machine-2.19.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b32daa965d13237536ea3afaa5ad61ade2b2d9314bc3a20196a0d2e1d7b57c6a", size = 17020, upload-time = "2025-08-19T17:21:30.653Z" }, - { url = "https://files.pythonhosted.org/packages/ed/97/c5fb51def06c0b2b6735332ad118ab35b4d9b85368792e5b638e99b1b686/time_machine-2.19.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:31cb43c8fd2d961f31bed0ff4e0026964d2b35e5de9e0fabbfecf756906d3612", size = 19360, upload-time = "2025-08-19T17:21:31.94Z" }, - { url = "https://files.pythonhosted.org/packages/2d/4e/2d795f7d6b7f5205ffe737a05bb1cf19d8038233b797062b2ef412b8512b/time_machine-2.19.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:bdf481a75afc6bff3e520db594501975b652f7def21cd1de6aa971d35ba644e6", size = 15033, upload-time = "2025-08-19T17:21:32.934Z" }, - { url = "https://files.pythonhosted.org/packages/dd/32/9bad501e360b4e758c58fae616ca5f8c7ad974b343f2463a15b2bf77a366/time_machine-2.19.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:00bee4bb950ac6a08d62af78e4da0cf2b4fc2abf0de2320d0431bf610db06e7c", size = 33379, upload-time = "2025-08-19T17:21:33.925Z" }, - { url = "https://files.pythonhosted.org/packages/a3/45/eda0ca4d793dfd162478d6163759b1c6ce7f6e61daa7fd7d62b31f21f87f/time_machine-2.19.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9f02199490906582302ce09edd32394fb393271674c75d7aa76c7a3245f16003", size = 35123, upload-time = "2025-08-19T17:21:34.945Z" }, - { url = "https://files.pythonhosted.org/packages/f0/5a/97e16325442ae5731fcaac794f0a1ef9980eff8a5491e58201d7eb814a34/time_machine-2.19.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e35726c7ba625f844c13b1fc0d4f81f394eefaee1d3a094a9093251521f2ef15", size = 36588, upload-time = "2025-08-19T17:21:35.975Z" }, - { url = "https://files.pythonhosted.org/packages/e8/9d/bf0b2ccc930cc4a316f26f1c78d3f313cd0fa13bb7480369b730a8f129db/time_machine-2.19.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:304315023999cd401ff02698870932b893369e1cfeb2248d09f6490507a92e97", size = 35013, upload-time = "2025-08-19T17:21:37.017Z" }, - { url = "https://files.pythonhosted.org/packages/f0/5a/39ac6a3078174f9715d88364871348b249631f12e76de1b862433b3f8862/time_machine-2.19.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9765d4f003f263ea8bfd90d2d15447ca4b3dfa181922cf6cf808923b02ac180a", size = 33303, upload-time = "2025-08-19T17:21:38.352Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ac/d8646baf9f95f2e792a6d7a7b35e92fca253c4a992afff801beafae0e5c2/time_machine-2.19.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7837ef3fd5911eb9b480909bb93d922737b6bdecea99dfcedb0a03807de9b2d3", size = 34440, upload-time = "2025-08-19T17:21:39.382Z" }, - { url = "https://files.pythonhosted.org/packages/ce/8b/8b6568c5ae966d80ead03ab537be3c6acf2af06fb501c2d466a3162c6295/time_machine-2.19.0-cp314-cp314-win32.whl", hash = "sha256:4bb5bd43b1bdfac3007b920b51d8e761f024ed465cfeec63ac4296922a4ec428", size = 17162, upload-time = "2025-08-19T17:21:40.381Z" }, - { url = "https://files.pythonhosted.org/packages/46/a5/211c1ab4566eba5308b2dc001b6349e3a032e3f6afa67ca2f27ea6b27af5/time_machine-2.19.0-cp314-cp314-win_amd64.whl", hash = "sha256:f583bbd0aa8ab4a7c45a684bf636d9e042d466e30bcbae1d13e7541e2cbe7207", size = 18040, upload-time = "2025-08-19T17:21:41.363Z" }, - { url = "https://files.pythonhosted.org/packages/b8/fc/4c2fb705f6371cb83824da45a8b967514a922fc092a0ef53979334d97a70/time_machine-2.19.0-cp314-cp314-win_arm64.whl", hash = "sha256:f379c6f8a6575a8284592179cf528ce89373f060301323edcc44f1fa1d37be12", size = 16752, upload-time = "2025-08-19T17:21:42.336Z" }, - { url = "https://files.pythonhosted.org/packages/79/ab/6437d18f31c666b5116c97572a282ac2590a82a0a9867746a6647eaf4613/time_machine-2.19.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:a3b8981f9c663b0906b05ab4d0ca211fae4b63b47c6ec26de5374fe56c836162", size = 20057, upload-time = "2025-08-19T17:21:43.35Z" }, - { url = "https://files.pythonhosted.org/packages/6c/a2/e03639ec2ba7200328bbcad8a2b2b1d5fccca9cceb9481b164a1cabdcb33/time_machine-2.19.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8e9c6363893e7f52c226afbebb23e825259222d100e67dfd24c8a6d35f1a1907", size = 15430, upload-time = "2025-08-19T17:21:44.725Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ff/39e63a48e840f3e36ce24846ee51dd99c6dba635659b1750a2993771e88e/time_machine-2.19.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:206fcd6c9a6f00cac83db446ad1effc530a8cec244d2780af62db3a2d0a9871b", size = 39622, upload-time = "2025-08-19T17:21:45.821Z" }, - { url = "https://files.pythonhosted.org/packages/9a/2e/ee5ac79c4954768705801e54817c7d58e07e25a0bb227e775f501f3e2122/time_machine-2.19.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bf33016a1403c123373ffaeff25e26e69d63bf2c63b6163932efed94160db7ef", size = 41235, upload-time = "2025-08-19T17:21:46.783Z" }, - { url = "https://files.pythonhosted.org/packages/3a/3e/9af5f39525e779185c77285b8bbae15340eeeaa0afb33d458bc8b47d459b/time_machine-2.19.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9247c4bb9bbd3ff584ef4efbdec8efd9f37aa08bcfc4728bde1e489c2cb445bd", size = 44276, upload-time = "2025-08-19T17:21:47.759Z" }, - { url = "https://files.pythonhosted.org/packages/59/fe/572c7443cc27140bbeae3947279bbd4a120f9e8622253a20637f260b7813/time_machine-2.19.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:77f9bb0b86758d1f2d9352642c874946ad5815df53ef4ca22eb9d532179fe50d", size = 42330, upload-time = "2025-08-19T17:21:48.881Z" }, - { url = "https://files.pythonhosted.org/packages/cf/24/1a81c2e08ee7dae13ec8ceed27a29afa980c3d63852e42f1e023bf0faa03/time_machine-2.19.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0b529e262df3b9c449f427385f4d98250828c879168c2e00eec844439f40b370", size = 39281, upload-time = "2025-08-19T17:21:49.907Z" }, - { url = "https://files.pythonhosted.org/packages/d2/60/6f0d6e5108978ca1a2a4ffb4d1c7e176d9199bb109fd44efe2680c60b52a/time_machine-2.19.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9199246e31cdc810e5d89cb71d09144c4d745960fdb0824da4994d152aca3303", size = 40201, upload-time = "2025-08-19T17:21:50.953Z" }, - { url = "https://files.pythonhosted.org/packages/73/b9/3ea4951e8293b0643feb98c0b9a176fa822154f1810835db3f282968ab10/time_machine-2.19.0-cp314-cp314t-win32.whl", hash = "sha256:0fe81bae55b7aefc2c2a34eb552aa82e6c61a86b3353a3c70df79b9698cb02ca", size = 17743, upload-time = "2025-08-19T17:21:51.948Z" }, - { url = "https://files.pythonhosted.org/packages/e4/8b/cd802884ca8a98e2b6cdc2397d57dd12ff8a7d1481e06fc3fad3d4e7e5ff/time_machine-2.19.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7253791b8d7e7399fbeed7a8193cb01bc004242864306288797056badbdaf80b", size = 18956, upload-time = "2025-08-19T17:21:52.997Z" }, - { url = "https://files.pythonhosted.org/packages/c6/49/cabb1593896082fd55e34768029b8b0ca23c9be8b2dc127e0fc14796d33e/time_machine-2.19.0-cp314-cp314t-win_arm64.whl", hash = "sha256:536bd1ac31ab06a1522e7bf287602188f502dc19d122b1502c4f60b1e8efac79", size = 17068, upload-time = "2025-08-19T17:21:54.064Z" }, - { url = "https://files.pythonhosted.org/packages/d6/05/0608376c3167afe6cf7cdfd2b05c142ea4c42616eee9ba06d1799965806a/time_machine-2.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8bb00b30ec9fe56d01e9812df1ffe39f331437cef9bfaebcc81c83f7f8f8ee2", size = 19659, upload-time = "2025-08-19T17:21:55.426Z" }, - { url = "https://files.pythonhosted.org/packages/11/c4/72eb8c7b36830cf36c51d7bc2f1ac313d68881c3a58040fb6b42c4523d20/time_machine-2.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d821c60efc08a97cc11e5482798e6fd5eba5c0f22a02db246b50895dbdc0de41", size = 15153, upload-time = "2025-08-19T17:21:56.505Z" }, - { url = "https://files.pythonhosted.org/packages/89/1a/0782e1f5c8ab8809ebd992709e1bb69d67600191baa023af7a5d32023a3c/time_machine-2.19.0-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fb051aec7b3b6e96a200d911c225901e6133ff3da11e470e24111a53bbc13637", size = 32555, upload-time = "2025-08-19T17:21:57.74Z" }, - { url = "https://files.pythonhosted.org/packages/94/b0/8ef58e2f6321851d5900ca3d18044938832c2ed42a2ac7570ca6aa29768a/time_machine-2.19.0-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fe59909d95a2ef5e01ce3354fdea3908404c2932c2069f00f66dff6f27e9363e", size = 34185, upload-time = "2025-08-19T17:21:59.361Z" }, - { url = "https://files.pythonhosted.org/packages/82/74/ce0c9867f788c1fb22c417ec1aae47a24117e53d51f6ff97d7c6ca5392f6/time_machine-2.19.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29e84b8682645b16eb6f9e8ec11c35324ad091841a11cf4fc3fc7f6119094c89", size = 35917, upload-time = "2025-08-19T17:22:00.421Z" }, - { url = "https://files.pythonhosted.org/packages/d2/70/6f97a8f552dbaa66feb10170b5726dab74bc531673d1ed9d6f271547e54c/time_machine-2.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a11f1c0e0d06023dc01614c964e256138913551d3ae6dca5148f79081156336", size = 34584, upload-time = "2025-08-19T17:22:01.447Z" }, - { url = "https://files.pythonhosted.org/packages/48/c8/cf139088ce537c15d7f03cf56ec317d3a5cfb520e30aa711ea0248d0ae8a/time_machine-2.19.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:57a235a6307c54df50e69f1906e2f199e47da91bde4b886ee05aff57fe4b6bf6", size = 32608, upload-time = "2025-08-19T17:22:02.548Z" }, - { url = "https://files.pythonhosted.org/packages/b1/17/0ec41ef7a30c6753fb226a28b74162b264b35724905ced4098f2f5076ded/time_machine-2.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:426aba552f7af9604adad9ef570c859af7c1081d878db78089fac159cd911b0a", size = 33686, upload-time = "2025-08-19T17:22:03.606Z" }, - { url = "https://files.pythonhosted.org/packages/b0/19/586f15159083ec84f178d494c60758c46603b00c9641b04deb63f1950128/time_machine-2.19.0-cp39-cp39-win32.whl", hash = "sha256:67772c7197a3a712d1b970ed545c6e98db73524bd90e245fd3c8fa7ad7630768", size = 17133, upload-time = "2025-08-19T17:22:04.989Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c2/bfe4b906a9fe0bf2d011534314212ed752d6b8f392c9c82f6ac63dccc5ab/time_machine-2.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:011d7859089263204dc5fdf83dce7388f986fe833c9381d6106b4edfda2ebd3e", size = 17972, upload-time = "2025-08-19T17:22:06.026Z" }, - { url = "https://files.pythonhosted.org/packages/5d/73/182343eba05aa5787732aaa68f3b3feb5e40ddf86b928ae941be45646393/time_machine-2.19.0-cp39-cp39-win_arm64.whl", hash = "sha256:e1af66550fa4685434f00002808a525f176f1f92746646c0019bb86fbff48b27", size = 16820, upload-time = "2025-08-19T17:22:07.227Z" }, -] - -[[package]] -name = "time-machine" -version = "3.2.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra == 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra == 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", - "python_full_version >= '3.10' and extra != 'group-11-dedalus-sdk-pydantic-v1' and extra != 'group-11-dedalus-sdk-pydantic-v2'", -] -sdist = { url = "https://files.pythonhosted.org/packages/02/fc/37b02f6094dbb1f851145330460532176ed2f1dc70511a35828166c41e52/time_machine-3.2.0.tar.gz", hash = "sha256:a4ddd1cea17b8950e462d1805a42b20c81eb9aafc8f66b392dd5ce997e037d79", size = 14804, upload-time = "2025-12-17T23:33:02.599Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/31/6bf41cb4a326230518d9b76c910dfc11d4fc23444d1cbfdf2d7652bd99f4/time_machine-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:68142c070e78b62215d8029ec7394905083a4f9aacb0a2a11514ce70b5951b13", size = 19447, upload-time = "2025-12-17T23:31:30.181Z" }, - { url = "https://files.pythonhosted.org/packages/fa/14/d71ce771712e1cbfa15d8c24452225109262b16cb6caaf967e9f60662b67/time_machine-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:161bbd0648802ffdfcb4bb297ecb26b3009684a47d3a4dedb90bc549df4fa2ad", size = 15432, upload-time = "2025-12-17T23:31:31.381Z" }, - { url = "https://files.pythonhosted.org/packages/8b/d6/dcb43a11f8029561996fad58ff9d3dc5e6d7f32b74f0745a2965d7e4b4f3/time_machine-3.2.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1359ba8c258be695ba69253bc84db882fd616fe69b426cc6056536da2c7bf68e", size = 32956, upload-time = "2025-12-17T23:31:32.469Z" }, - { url = "https://files.pythonhosted.org/packages/77/da/d802cd3c335c414f9b11b479f7459aa72df5de6485c799966cfdf8856d53/time_machine-3.2.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c85b169998ca2c24a78fb214586ec11c4cad56d9c38f55ad8326235cb481c884", size = 34556, upload-time = "2025-12-17T23:31:33.946Z" }, - { url = "https://files.pythonhosted.org/packages/85/ee/51ad553514ab0b940c7c82c6e1519dd10fd06ac07b32039a1d153ef09c88/time_machine-3.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65b9367cb8a10505bc8f67da0da514ba20fa816fc47e11f434f7c60350322b4c", size = 36101, upload-time = "2025-12-17T23:31:35.462Z" }, - { url = "https://files.pythonhosted.org/packages/11/39/938b111b5bb85a2b07502d0f9d8a704fc75bd760d62e76bce23c89ed16c9/time_machine-3.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9faca6a0f1973d7df3233c951fc2a11ff0c54df74087d8aaf41ae3deb19d0893", size = 34905, upload-time = "2025-12-17T23:31:36.543Z" }, - { url = "https://files.pythonhosted.org/packages/dd/50/0951f73b23e76455de0b4a3a58ac5a24bd8d10489624b1c5e03f10c6fc0b/time_machine-3.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:213b1ada7f385d467e598999b642eda4a8e89ae10ad5dc4f5d8f672cbf604261", size = 33012, upload-time = "2025-12-17T23:31:37.967Z" }, - { url = "https://files.pythonhosted.org/packages/4f/95/5304912d3dcecc4e14ed222dbe0396352efdf8497534abc3c9edd67a7528/time_machine-3.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:160b6afd94c39855af04d39c58e4cf602406abd6d79427ab80e830ea71789cfb", size = 34104, upload-time = "2025-12-17T23:31:39.449Z" }, - { url = "https://files.pythonhosted.org/packages/d4/1c/af56518652ec7adac4ced193b7a42c4ff354fef28a412b3b5ffa5763aead/time_machine-3.2.0-cp310-cp310-win32.whl", hash = "sha256:c15d9ac257c78c124d112e4fc91fa9f3dcb004bdda913c19f0e7368d713cf080", size = 17468, upload-time = "2025-12-17T23:31:40.432Z" }, - { url = "https://files.pythonhosted.org/packages/48/15/0213f00ca3cf6fe1c9fdbd7fd467e801052fc85534f30c0e4684bd474190/time_machine-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:3bf0f428487f93b8fe9d27aa01eccc817885da3290b467341b4a4a795e1d1891", size = 18313, upload-time = "2025-12-17T23:31:41.617Z" }, - { url = "https://files.pythonhosted.org/packages/77/e4/811f96aa7a634b2b264d9a476f3400e710744dda503b4ad87a5c76db32c9/time_machine-3.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:347f6be2129fcd35b1c94b9387fcb2cbe7949b1e649228c5f22949a811b78976", size = 17037, upload-time = "2025-12-17T23:31:42.924Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e1/03aae5fbaa53859f665094af696338fc7cae733d926a024af69982712350/time_machine-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c188a9dda9fcf975022f1b325b466651b96a4dfc223c523ed7ed8d979f9bf3e8", size = 19143, upload-time = "2025-12-17T23:31:44.258Z" }, - { url = "https://files.pythonhosted.org/packages/75/8f/98cb17bebb52b22ff4ec26984dd44280f9c71353c3bae0640a470e6683e5/time_machine-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17245f1cc2dd13f9d63a174be59bb2684a9e5e0a112ab707e37be92068cd655f", size = 15273, upload-time = "2025-12-17T23:31:45.246Z" }, - { url = "https://files.pythonhosted.org/packages/dd/2f/ca11e4a7897234bb9331fcc5f4ed4714481ba4012370cc79a0ae8c42ea0a/time_machine-3.2.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d9bd1de1996e76efd36ae15970206c5089fb3728356794455bd5cd8d392b5537", size = 31049, upload-time = "2025-12-17T23:31:46.613Z" }, - { url = "https://files.pythonhosted.org/packages/cf/ad/d17d83a59943094e6b6c6a3743caaf6811b12203c3e07a30cc7bcc2ab7ee/time_machine-3.2.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:98493cd50e8b7f941eab69b9e18e697ad69db1a0ec1959f78f3d7b0387107e5c", size = 32632, upload-time = "2025-12-17T23:31:47.72Z" }, - { url = "https://files.pythonhosted.org/packages/71/50/d60576d047a0dfb5638cdfb335e9c3deb6e8528544fa0b3966a8480f72b7/time_machine-3.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:31f2a33d595d9f91eb9bc7f157f0dc5721f5789f4c4a9e8b852cdedb2a7d9b16", size = 34289, upload-time = "2025-12-17T23:31:48.913Z" }, - { url = "https://files.pythonhosted.org/packages/fa/fe/4afa602dbdebddde6d0ea4a7fe849e49b9bb85dc3fb415725a87ccb4b471/time_machine-3.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9f78ac4213c10fbc44283edd1a29cfb7d3382484f4361783ddc057292aaa1889", size = 33175, upload-time = "2025-12-17T23:31:50.611Z" }, - { url = "https://files.pythonhosted.org/packages/0d/87/c152e23977c1d7d7c94eb3ed3ea45cc55971796205125c6fdff40db2c60f/time_machine-3.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c1326b09e947b360926d529a96d1d9e126ce120359b63b506ecdc6ee20755c23", size = 31170, upload-time = "2025-12-17T23:31:51.645Z" }, - { url = "https://files.pythonhosted.org/packages/80/af/54acf51d0f3ade3b51eab73df6192937c9a938753ef5456dff65eb8630be/time_machine-3.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9f2949f03d15264cc15c38918a2cda8966001f0f4ebe190cbfd9c56d91aed8ac", size = 32292, upload-time = "2025-12-17T23:31:52.803Z" }, - { url = "https://files.pythonhosted.org/packages/cc/bc/3745963f36e75661a807196428639327a366f4332f35f1f775c074d4062f/time_machine-3.2.0-cp311-cp311-win32.whl", hash = "sha256:6dfe48e0499e6e16751476b9799e67be7514e6ef04cdf39571ef95a279645831", size = 17349, upload-time = "2025-12-17T23:31:54.19Z" }, - { url = "https://files.pythonhosted.org/packages/82/a2/057469232a99d1f5a0160ae7c5bae7b095c9168b333dd598fcbcfbc1c87b/time_machine-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:809bdf267a29189c304154873620fe0bcc0c9513295fa46b19e21658231c4915", size = 18191, upload-time = "2025-12-17T23:31:55.472Z" }, - { url = "https://files.pythonhosted.org/packages/79/d8/bf9c8de57262ee7130d92a6ed49ed6a6e40a36317e46979428d373630c12/time_machine-3.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:a3f4c17fa90f54902a3f8692c75caf67be87edc3429eeb71cb4595da58198f8e", size = 16905, upload-time = "2025-12-17T23:31:56.658Z" }, - { url = "https://files.pythonhosted.org/packages/71/8b/080c8eedcd67921a52ba5bd0e075362062509ab63c86fc1a0442fad241a6/time_machine-3.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cc4bee5b0214d7dc4ebc91f4a4c600f1a598e9b5606ac751f42cb6f6740b1dbb", size = 19255, upload-time = "2025-12-17T23:31:58.057Z" }, - { url = "https://files.pythonhosted.org/packages/66/17/0e5291e9eb705bf8a5a1305f826e979af307bbeb79def4ddbf4b3f9a81e0/time_machine-3.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ca036304b4460ae2fdc1b52dd8b1fa7cf1464daa427fc49567413c09aa839c1", size = 15360, upload-time = "2025-12-17T23:31:59.048Z" }, - { url = "https://files.pythonhosted.org/packages/8b/e8/9ab87b71d2e2b62463b9b058b7ae7ac09fb57f8fcd88729dec169d304340/time_machine-3.2.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5442735b41d7a2abc2f04579b4ca6047ed4698a8338a4fec92c7c9423e7938cb", size = 33029, upload-time = "2025-12-17T23:32:00.413Z" }, - { url = "https://files.pythonhosted.org/packages/4b/26/b5ca19da6f25ea905b3e10a0ea95d697c1aeba0404803a43c68f1af253e6/time_machine-3.2.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:97da3e971e505cb637079fb07ab0bcd36e33279f8ecac888ff131f45ef1e4d8d", size = 34579, upload-time = "2025-12-17T23:32:01.431Z" }, - { url = "https://files.pythonhosted.org/packages/79/ca/6ac7ad5f10ea18cc1d9de49716ba38c32132c7b64532430d92ef240c116b/time_machine-3.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3cdda6dee4966e38aeb487309bb414c6cb23a81fc500291c77a8fcd3098832e7", size = 35961, upload-time = "2025-12-17T23:32:02.521Z" }, - { url = "https://files.pythonhosted.org/packages/33/67/390dd958bed395ab32d79a9fe61fe111825c0dd4ded54dbba7e867f171e6/time_machine-3.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:33d9efd302a6998bcc8baa4d84f259f8a4081105bd3d7f7af7f1d0abd3b1c8aa", size = 34668, upload-time = "2025-12-17T23:32:03.585Z" }, - { url = "https://files.pythonhosted.org/packages/da/57/c88fff034a4e9538b3ae7c68c9cfb283670b14d17522c5a8bc17d29f9a4b/time_machine-3.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3a0b0a33971f14145853c9bd95a6ab0353cf7e0019fa2a7aa1ae9fddfe8eab50", size = 32891, upload-time = "2025-12-17T23:32:04.656Z" }, - { url = "https://files.pythonhosted.org/packages/2d/70/ebbb76022dba0fec8f9156540fc647e4beae1680c787c01b1b6200e56d70/time_machine-3.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2d0be9e5f22c38082d247a2cdcd8a936504e9db60b7b3606855fb39f299e9548", size = 34080, upload-time = "2025-12-17T23:32:06.146Z" }, - { url = "https://files.pythonhosted.org/packages/db/9a/2ca9e7af3df540dc1c79e3de588adeddb7dcc2107829248e6969c4f14167/time_machine-3.2.0-cp312-cp312-win32.whl", hash = "sha256:3f74623648b936fdce5f911caf386c0a0b579456410975de8c0dfeaaffece1d8", size = 17371, upload-time = "2025-12-17T23:32:07.164Z" }, - { url = "https://files.pythonhosted.org/packages/d8/ce/21d23efc9c2151939af1b7ee4e60d86d661b74ef32b8eaa148f6fe8c899c/time_machine-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:34e26a41d994b5e4b205136a90e9578470386749cc9a2ecf51ca18f83ce25e23", size = 18132, upload-time = "2025-12-17T23:32:08.447Z" }, - { url = "https://files.pythonhosted.org/packages/2f/34/c2b70be483accf6db9e5d6c3139bce3c38fe51f898ccf64e8d3fe14fbf4d/time_machine-3.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:0615d3d82c418d6293f271c348945c5091a71f37e37173653d5c26d0e74b13a8", size = 16930, upload-time = "2025-12-17T23:32:09.477Z" }, - { url = "https://files.pythonhosted.org/packages/ee/cd/43ad5efc88298af3c59b66769cea7f055567a85071579ed40536188530c1/time_machine-3.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c421a8eb85a4418a7675a41bf8660224318c46cc62e4751c8f1ceca752059090", size = 19318, upload-time = "2025-12-17T23:32:10.518Z" }, - { url = "https://files.pythonhosted.org/packages/b0/f6/084010ef7f4a3f38b5a4900923d7c85b29e797655c4f6ee4ce54d903cca8/time_machine-3.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f4e758f7727d0058c4950c66b58200c187072122d6f7a98b610530a4233ea7b", size = 15390, upload-time = "2025-12-17T23:32:11.625Z" }, - { url = "https://files.pythonhosted.org/packages/25/aa/1cabb74134f492270dc6860cb7865859bf40ecf828be65972827646e91ad/time_machine-3.2.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:154bd3f75c81f70218b2585cc12b60762fb2665c507eec5ec5037d8756d9b4e0", size = 33115, upload-time = "2025-12-17T23:32:13.219Z" }, - { url = "https://files.pythonhosted.org/packages/5e/03/78c5d7dfa366924eb4dbfcc3fc917c39a4280ca234b12819cc1f16c03d88/time_machine-3.2.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d50cfe5ebea422c896ad8d278af9648412b7533b8ea6adeeee698a3fd9b1d3b7", size = 34705, upload-time = "2025-12-17T23:32:14.29Z" }, - { url = "https://files.pythonhosted.org/packages/86/93/d5e877c24541f674c6869ff6e9c56833369796010190252e92c9d7ae5f0f/time_machine-3.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:636576501724bd6a9124e69d86e5aef263479e89ef739c5db361469f0463a0a1", size = 36104, upload-time = "2025-12-17T23:32:15.354Z" }, - { url = "https://files.pythonhosted.org/packages/22/1c/d4bae72f388f67efc9609f89b012e434bb19d9549c7a7b47d6c7d9e5c55d/time_machine-3.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:40e6f40c57197fcf7ec32d2c563f4df0a82c42cdcc3cab27f688e98f6060df10", size = 34765, upload-time = "2025-12-17T23:32:16.434Z" }, - { url = "https://files.pythonhosted.org/packages/1d/c3/ac378cf301d527d8dfad2f0db6bad0dfb1ab73212eaa56d6b96ee5d9d20b/time_machine-3.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a1bcf0b846bbfc19a79bc19e3fa04d8c7b1e8101c1b70340ffdb689cd801ea53", size = 33010, upload-time = "2025-12-17T23:32:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/06/35/7ce897319accda7a6970b288a9a8c52d25227342a7508505a2b3d235b649/time_machine-3.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ae55a56c179f4fe7a62575ad5148b6ed82f6c7e5cf2f9a9ec65f2f5b067db5f5", size = 34185, upload-time = "2025-12-17T23:32:18.566Z" }, - { url = "https://files.pythonhosted.org/packages/bf/28/f922022269749cb02eee2b62919671153c4088994fa955a6b0e50327ff81/time_machine-3.2.0-cp313-cp313-win32.whl", hash = "sha256:a66fe55a107e46916007a391d4030479df8864ec6ad6f6a6528221befc5c886e", size = 17397, upload-time = "2025-12-17T23:32:19.605Z" }, - { url = "https://files.pythonhosted.org/packages/ee/dc/fd87cde397f4a7bea493152f0aca8fd569ec709cad9e0f2ca7011eb8c7f7/time_machine-3.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:30c9ce57165df913e4f74e285a8ab829ff9b7aa3e5ec0973f88f642b9a7b3d15", size = 18139, upload-time = "2025-12-17T23:32:20.991Z" }, - { url = "https://files.pythonhosted.org/packages/75/81/b8ce58233addc5d7d54d2fabc49dcbc02d79e3f079d150aa1bec3d5275ef/time_machine-3.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:89cad7e179e9bdcc84dcf09efe52af232c4cc7a01b3de868356bbd59d95bd9b8", size = 16964, upload-time = "2025-12-17T23:32:22.075Z" }, - { url = "https://files.pythonhosted.org/packages/67/e7/487f0ba5fe6c58186a5e1af2a118dfa2c160fedb37ef53a7e972d410408e/time_machine-3.2.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:59d71545e62525a4b85b6de9ab5c02ee3c61110fd7f636139914a2335dcbfc9c", size = 20000, upload-time = "2025-12-17T23:32:23.058Z" }, - { url = "https://files.pythonhosted.org/packages/e1/17/eb2c0054c8d44dd42df84ccd434539249a9c7d0b8eb53f799be2102500ab/time_machine-3.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:999672c621c35362bc28e03ca0c7df21500195540773c25993421fd8d6cc5003", size = 15657, upload-time = "2025-12-17T23:32:24.125Z" }, - { url = "https://files.pythonhosted.org/packages/43/21/93443b5d1dd850f8bb9442e90d817a9033dcce6bfbdd3aabbb9786251c80/time_machine-3.2.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5faf7397f0580c7b9d67288522c8d7863e85f0cffadc0f1fccdb2c3dfce5783e", size = 39216, upload-time = "2025-12-17T23:32:25.542Z" }, - { url = "https://files.pythonhosted.org/packages/9f/9e/18544cf8acc72bb1dc03762231c82ecc259733f4bb6770a7bbe5cd138603/time_machine-3.2.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3dd886ec49f1fa5a00e844f5947e5c0f98ce574750c24b7424c6f77fc1c3e87", size = 40764, upload-time = "2025-12-17T23:32:26.643Z" }, - { url = "https://files.pythonhosted.org/packages/27/f7/9fe9ce2795636a3a7467307af6bdf38bb613ddb701a8a5cd50ec713beb5e/time_machine-3.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da0ecd96bc7bbe450acaaabe569d84e81688f1be8ad58d1470e42371d145fb53", size = 43526, upload-time = "2025-12-17T23:32:27.693Z" }, - { url = "https://files.pythonhosted.org/packages/03/c1/a93e975ba9dec22e87ec92d18c28e67d36bd536f9119ffa439b2892b0c9c/time_machine-3.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:158220e946c1c4fb8265773a0282c88c35a7e3bb5d78e3561214e3b3231166f3", size = 41727, upload-time = "2025-12-17T23:32:28.985Z" }, - { url = "https://files.pythonhosted.org/packages/5f/fb/e3633e5a6bbed1c76bb2e9810dabc2f8467532ffcd29b9aed404b473061a/time_machine-3.2.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c1aee29bc54356f248d5d7dfdd131e12ca825e850a08c0ebdb022266d073013", size = 38952, upload-time = "2025-12-17T23:32:30.031Z" }, - { url = "https://files.pythonhosted.org/packages/82/3d/02e9fb2526b3d6b1b45bc8e4d912d95d1cd699d1a3f6df985817d37a0600/time_machine-3.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c8ed2224f09d25b1c2fc98683613aca12f90f682a427eabb68fc824d27014e4a", size = 39829, upload-time = "2025-12-17T23:32:31.075Z" }, - { url = "https://files.pythonhosted.org/packages/85/c8/c14265212436da8e0814c45463987b3f57de3eca4de023cc2eabb0c62ef3/time_machine-3.2.0-cp313-cp313t-win32.whl", hash = "sha256:3498719f8dab51da76d29a20c1b5e52ee7db083dddf3056af7fa69c1b94e1fe6", size = 17852, upload-time = "2025-12-17T23:32:32.079Z" }, - { url = "https://files.pythonhosted.org/packages/1d/bc/8acb13cf6149f47508097b158a9a8bec9ec4530a70cb406124e8023581f5/time_machine-3.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e0d90bee170b219e1d15e6a58164aa808f5170090e4f090bd0670303e34181b1", size = 18918, upload-time = "2025-12-17T23:32:33.106Z" }, - { url = "https://files.pythonhosted.org/packages/24/87/c443ee508c2708fd2514ccce9052f5e48888783ce690506919629ebc8eb0/time_machine-3.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:051de220fdb6e20d648111bbad423d9506fdbb2e44d4429cef3dc0382abf1fc2", size = 17261, upload-time = "2025-12-17T23:32:34.446Z" }, - { url = "https://files.pythonhosted.org/packages/61/70/b4b980d126ed155c78d1879c50d60c8dcbd47bd11cb14ee7be50e0dfc07f/time_machine-3.2.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:1398980c017fe5744d66f419e0115ee48a53b00b146d738e1416c225eb610b82", size = 19303, upload-time = "2025-12-17T23:32:35.796Z" }, - { url = "https://files.pythonhosted.org/packages/73/73/eaa33603c69a68fe2b6f54f9dd75481693d62f1d29676531002be06e2d1c/time_machine-3.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4f8f4e35f4191ef70c2ab8ff490761ee9051b891afce2bf86dde3918eb7b537b", size = 15431, upload-time = "2025-12-17T23:32:37.244Z" }, - { url = "https://files.pythonhosted.org/packages/76/10/b81e138e86cc7bab40cdb59d294b341e172201f4a6c84bb0ec080407977a/time_machine-3.2.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6db498686ecf6163c5aa8cf0bcd57bbe0f4081184f247edf3ee49a2612b584f9", size = 33206, upload-time = "2025-12-17T23:32:38.713Z" }, - { url = "https://files.pythonhosted.org/packages/d3/72/4deab446b579e8bd5dca91de98595c5d6bd6a17ce162abf5c5f2ce40d3d8/time_machine-3.2.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:027c1807efb74d0cd58ad16524dec94212fbe900115d70b0123399883657ac0f", size = 34792, upload-time = "2025-12-17T23:32:40.223Z" }, - { url = "https://files.pythonhosted.org/packages/2c/39/439c6b587ddee76d533fe972289d0646e0a5520e14dc83d0a30aeb5565f7/time_machine-3.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92432610c05676edd5e6946a073c6f0c926923123ce7caee1018dc10782c713d", size = 36187, upload-time = "2025-12-17T23:32:41.705Z" }, - { url = "https://files.pythonhosted.org/packages/4b/db/2da4368db15180989bab83746a857bde05ad16e78f326801c142bb747a06/time_machine-3.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c25586b62480eb77ef3d953fba273209478e1ef49654592cd6a52a68dfe56a67", size = 34855, upload-time = "2025-12-17T23:32:42.817Z" }, - { url = "https://files.pythonhosted.org/packages/88/84/120a431fee50bc4c241425bee4d3a4910df4923b7ab5f7dff1bf0c772f08/time_machine-3.2.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6bf3a2fa738d15e0b95d14469a0b8ea42635467408d8b490e263d5d45c9a177f", size = 33222, upload-time = "2025-12-17T23:32:43.94Z" }, - { url = "https://files.pythonhosted.org/packages/f9/ea/89cfda82bb8c57ff91bb9a26751aa234d6d90e9b4d5ab0ad9dce0f9f0329/time_machine-3.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ce76b82276d7ad2a66cdc85dad4df19d1422b69183170a34e8fbc4c3f35502f7", size = 34270, upload-time = "2025-12-17T23:32:45.037Z" }, - { url = "https://files.pythonhosted.org/packages/8a/aa/235357da4f69a51a8d35fcbfcfa77cdc7dc24f62ae54025006570bda7e2d/time_machine-3.2.0-cp314-cp314-win32.whl", hash = "sha256:14d6778273c543441863dff712cd1d7803dee946b18de35921eb8df10714539d", size = 17544, upload-time = "2025-12-17T23:32:46.099Z" }, - { url = "https://files.pythonhosted.org/packages/7b/51/6c8405a7276be79693b792cff22ce41067ec05db26a7d02f2d5b06324434/time_machine-3.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:cbf821da96dbc80d349fa9e7c36e670b41d68a878d28c8850057992fed430eef", size = 18423, upload-time = "2025-12-17T23:32:47.468Z" }, - { url = "https://files.pythonhosted.org/packages/d9/03/a3cf419e20c35fc203c6e4fed48b5b667c1a2b4da456d9971e605f73ecef/time_machine-3.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:71c75d71f8e68abc8b669bca26ed2ddd558430a6c171e32b8620288565f18c0e", size = 17050, upload-time = "2025-12-17T23:32:48.91Z" }, - { url = "https://files.pythonhosted.org/packages/86/a1/142de946dc4393f910bf4564b5c3ba819906e1f49b06c9cb557519c849e4/time_machine-3.2.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4e374779021446fc2b5c29d80457ec9a3b1a5df043dc2aae07d7c1415d52323c", size = 19991, upload-time = "2025-12-17T23:32:49.933Z" }, - { url = "https://files.pythonhosted.org/packages/ee/62/7f17def6289901f94726921811a16b9adce46e666362c75d45730c60274f/time_machine-3.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:122310a6af9c36e9a636da32830e591e7923e8a07bdd0a43276c3a36c6821c90", size = 15707, upload-time = "2025-12-17T23:32:50.969Z" }, - { url = "https://files.pythonhosted.org/packages/5d/d3/3502fb9bd3acb159c18844b26c43220201a0d4a622c0c853785d07699a92/time_machine-3.2.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ba3eeb0f018cc362dd8128befa3426696a2e16dd223c3fb695fde184892d4d8c", size = 39207, upload-time = "2025-12-17T23:32:52.033Z" }, - { url = "https://files.pythonhosted.org/packages/5a/be/8b27f4aa296fda14a5a2ad7f588ddd450603c33415ab3f8e85b2f1a44678/time_machine-3.2.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:77d38ba664b381a7793f8786efc13b5004f0d5f672dae814430445b8202a67a6", size = 40764, upload-time = "2025-12-17T23:32:53.167Z" }, - { url = "https://files.pythonhosted.org/packages/42/cd/fe4c4e5c8ab6d48fab3624c32be9116fb120173a35fe67e482e5cf68b3d2/time_machine-3.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f09abeb8f03f044d72712207e0489a62098ad3ad16dac38927fcf80baca4d6a7", size = 43508, upload-time = "2025-12-17T23:32:54.597Z" }, - { url = "https://files.pythonhosted.org/packages/b4/28/5a3ba2fce85b97655a425d6bb20a441550acd2b304c96b2c19d3839f721a/time_machine-3.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6b28367ce4f73987a55e230e1d30a57a3af85da8eb1a140074eb6e8c7e6ef19f", size = 41712, upload-time = "2025-12-17T23:32:55.781Z" }, - { url = "https://files.pythonhosted.org/packages/81/58/e38084be7fdabb4835db68a3a47e58c34182d79fc35df1ecbe0db2c5359f/time_machine-3.2.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:903c7751c904581da9f7861c3015bed7cdc40047321291d3694a3cdc783bbca3", size = 38939, upload-time = "2025-12-17T23:32:56.867Z" }, - { url = "https://files.pythonhosted.org/packages/40/d0/ad3feb0a392ef4e0c08bc32024950373ddc0669002cbdcbb9f3bf0c2d114/time_machine-3.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:528217cad85ede5f85c8bc78b0341868d3c3cfefc6ecb5b622e1cacb6c73247b", size = 39837, upload-time = "2025-12-17T23:32:58.283Z" }, - { url = "https://files.pythonhosted.org/packages/5b/9e/5f4b2ea63b267bd78f3245e76f5528836611b5f2d30b5e7300a722fe4428/time_machine-3.2.0-cp314-cp314t-win32.whl", hash = "sha256:75724762ffd517e7e80aaec1fad1ff5a7414bd84e2b3ee7a0bacfeb67c14926e", size = 18091, upload-time = "2025-12-17T23:32:59.403Z" }, - { url = "https://files.pythonhosted.org/packages/39/6f/456b1f4d2700ae02b19eba830f870596a4b89b74bac3b6c80666f1b108c5/time_machine-3.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2526abbd053c5bca898d1b3e7898eec34626b12206718d8c7ce88fd12c1c9c5c", size = 19208, upload-time = "2025-12-17T23:33:00.488Z" }, - { url = "https://files.pythonhosted.org/packages/2f/22/8063101427ecd3d2652aada4d21d0876b07a3dc789125bca2ee858fec3ed/time_machine-3.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:7f2fb6784b414edbe2c0b558bfaab0c251955ba27edd62946cce4a01675a992c", size = 17359, upload-time = "2025-12-17T23:33:01.54Z" }, -] - -[[package]] -name = "tomli" -version = "2.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" }, - { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" }, - { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" }, - { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" }, - { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" }, - { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" }, - { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" }, - { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" }, - { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" }, - { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" }, - { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" }, - { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" }, - { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" }, - { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" }, - { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" }, - { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" }, - { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" }, - { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" }, - { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" }, - { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" }, - { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" }, - { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" }, - { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" }, - { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" }, - { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" }, - { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" }, - { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" }, - { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" }, - { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" }, - { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" }, - { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" }, - { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" }, - { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" }, - { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" }, - { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" }, - { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" }, - { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" }, - { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" }, - { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" }, - { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" }, - { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" }, - { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" }, - { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" }, - { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" }, - { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, -] - -[[package]] -name = "typing-inspection" -version = "0.4.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "extra == 'group-11-dedalus-sdk-pydantic-v2' or extra != 'group-11-dedalus-sdk-pydantic-v1'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, -] - -[[package]] -name = "yarl" -version = "1.22.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/43/a2204825342f37c337f5edb6637040fa14e365b2fcc2346960201d457579/yarl-1.22.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", size = 140517, upload-time = "2025-10-06T14:08:42.494Z" }, - { url = "https://files.pythonhosted.org/packages/44/6f/674f3e6f02266428c56f704cd2501c22f78e8b2eeb23f153117cc86fb28a/yarl-1.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", size = 93495, upload-time = "2025-10-06T14:08:46.2Z" }, - { url = "https://files.pythonhosted.org/packages/b8/12/5b274d8a0f30c07b91b2f02cba69152600b47830fcfb465c108880fcee9c/yarl-1.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", size = 94400, upload-time = "2025-10-06T14:08:47.855Z" }, - { url = "https://files.pythonhosted.org/packages/e2/7f/df1b6949b1fa1aa9ff6de6e2631876ad4b73c4437822026e85d8acb56bb1/yarl-1.22.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", size = 347545, upload-time = "2025-10-06T14:08:49.683Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/f92ed93bd6cd77872ab6c3462df45ca45cd058d8f1d0c9b4f54c1704429f/yarl-1.22.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", size = 319598, upload-time = "2025-10-06T14:08:51.215Z" }, - { url = "https://files.pythonhosted.org/packages/c3/97/ac3f3feae7d522cf7ccec3d340bb0b2b61c56cb9767923df62a135092c6b/yarl-1.22.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", size = 363893, upload-time = "2025-10-06T14:08:53.144Z" }, - { url = "https://files.pythonhosted.org/packages/06/49/f3219097403b9c84a4d079b1d7bda62dd9b86d0d6e4428c02d46ab2c77fc/yarl-1.22.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", size = 371240, upload-time = "2025-10-06T14:08:55.036Z" }, - { url = "https://files.pythonhosted.org/packages/35/9f/06b765d45c0e44e8ecf0fe15c9eacbbde342bb5b7561c46944f107bfb6c3/yarl-1.22.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", size = 346965, upload-time = "2025-10-06T14:08:56.722Z" }, - { url = "https://files.pythonhosted.org/packages/c5/69/599e7cea8d0fcb1694323b0db0dda317fa3162f7b90166faddecf532166f/yarl-1.22.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", size = 342026, upload-time = "2025-10-06T14:08:58.563Z" }, - { url = "https://files.pythonhosted.org/packages/95/6f/9dfd12c8bc90fea9eab39832ee32ea48f8e53d1256252a77b710c065c89f/yarl-1.22.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", size = 335637, upload-time = "2025-10-06T14:09:00.506Z" }, - { url = "https://files.pythonhosted.org/packages/57/2e/34c5b4eb9b07e16e873db5b182c71e5f06f9b5af388cdaa97736d79dd9a6/yarl-1.22.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", size = 359082, upload-time = "2025-10-06T14:09:01.936Z" }, - { url = "https://files.pythonhosted.org/packages/31/71/fa7e10fb772d273aa1f096ecb8ab8594117822f683bab7d2c5a89914c92a/yarl-1.22.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", size = 357811, upload-time = "2025-10-06T14:09:03.445Z" }, - { url = "https://files.pythonhosted.org/packages/26/da/11374c04e8e1184a6a03cf9c8f5688d3e5cec83ed6f31ad3481b3207f709/yarl-1.22.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", size = 351223, upload-time = "2025-10-06T14:09:05.401Z" }, - { url = "https://files.pythonhosted.org/packages/82/8f/e2d01f161b0c034a30410e375e191a5d27608c1f8693bab1a08b089ca096/yarl-1.22.0-cp310-cp310-win32.whl", hash = "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", size = 82118, upload-time = "2025-10-06T14:09:11.148Z" }, - { url = "https://files.pythonhosted.org/packages/62/46/94c76196642dbeae634c7a61ba3da88cd77bed875bf6e4a8bed037505aa6/yarl-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", size = 86852, upload-time = "2025-10-06T14:09:12.958Z" }, - { url = "https://files.pythonhosted.org/packages/af/af/7df4f179d3b1a6dcb9a4bd2ffbc67642746fcafdb62580e66876ce83fff4/yarl-1.22.0-cp310-cp310-win_arm64.whl", hash = "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", size = 82012, upload-time = "2025-10-06T14:09:14.664Z" }, - { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, - { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" }, - { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" }, - { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" }, - { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" }, - { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" }, - { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" }, - { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" }, - { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" }, - { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" }, - { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" }, - { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" }, - { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" }, - { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, - { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, - { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, - { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, - { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, - { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, - { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, - { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, - { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, - { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, - { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, - { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, - { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, - { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, - { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, - { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, - { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, - { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, - { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, - { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, - { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, - { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, - { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, - { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, - { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, - { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, - { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, - { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, - { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, - { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, - { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, - { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, - { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, - { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, - { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, - { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, - { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, - { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, - { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, - { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, - { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, - { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, - { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" }, - { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" }, - { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" }, - { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" }, - { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" }, - { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" }, - { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" }, - { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" }, - { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" }, - { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" }, - { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" }, - { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" }, - { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" }, - { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" }, - { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" }, - { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" }, - { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" }, - { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" }, - { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" }, - { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" }, - { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" }, - { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, - { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, - { url = "https://files.pythonhosted.org/packages/94/fd/6480106702a79bcceda5fd9c63cb19a04a6506bd5ce7fd8d9b63742f0021/yarl-1.22.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748", size = 141301, upload-time = "2025-10-06T14:12:19.01Z" }, - { url = "https://files.pythonhosted.org/packages/42/e1/6d95d21b17a93e793e4ec420a925fe1f6a9342338ca7a563ed21129c0990/yarl-1.22.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859", size = 93864, upload-time = "2025-10-06T14:12:21.05Z" }, - { url = "https://files.pythonhosted.org/packages/32/58/b8055273c203968e89808413ea4c984988b6649baabf10f4522e67c22d2f/yarl-1.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9", size = 94706, upload-time = "2025-10-06T14:12:23.287Z" }, - { url = "https://files.pythonhosted.org/packages/18/91/d7bfbc28a88c2895ecd0da6a874def0c147de78afc52c773c28e1aa233a3/yarl-1.22.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054", size = 347100, upload-time = "2025-10-06T14:12:28.527Z" }, - { url = "https://files.pythonhosted.org/packages/bd/e8/37a1e7b99721c0564b1fc7b0a4d1f595ef6fb8060d82ca61775b644185f7/yarl-1.22.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b", size = 318902, upload-time = "2025-10-06T14:12:30.528Z" }, - { url = "https://files.pythonhosted.org/packages/1c/ef/34724449d7ef2db4f22df644f2dac0b8a275d20f585e526937b3ae47b02d/yarl-1.22.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60", size = 363302, upload-time = "2025-10-06T14:12:32.295Z" }, - { url = "https://files.pythonhosted.org/packages/8a/04/88a39a5dad39889f192cce8d66cc4c58dbeca983e83f9b6bf23822a7ed91/yarl-1.22.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890", size = 370816, upload-time = "2025-10-06T14:12:34.01Z" }, - { url = "https://files.pythonhosted.org/packages/6b/1f/5e895e547129413f56c76be2c3ce4b96c797d2d0ff3e16a817d9269b12e6/yarl-1.22.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba", size = 346465, upload-time = "2025-10-06T14:12:35.977Z" }, - { url = "https://files.pythonhosted.org/packages/11/13/a750e9fd6f9cc9ed3a52a70fe58ffe505322f0efe0d48e1fd9ffe53281f5/yarl-1.22.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca", size = 341506, upload-time = "2025-10-06T14:12:37.788Z" }, - { url = "https://files.pythonhosted.org/packages/3c/67/bb6024de76e7186611ebe626aec5b71a2d2ecf9453e795f2dbd80614784c/yarl-1.22.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba", size = 335030, upload-time = "2025-10-06T14:12:39.775Z" }, - { url = "https://files.pythonhosted.org/packages/a2/be/50b38447fd94a7992996a62b8b463d0579323fcfc08c61bdba949eef8a5d/yarl-1.22.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b", size = 358560, upload-time = "2025-10-06T14:12:41.547Z" }, - { url = "https://files.pythonhosted.org/packages/e2/89/c020b6f547578c4e3dbb6335bf918f26e2f34ad0d1e515d72fd33ac0c635/yarl-1.22.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e", size = 357290, upload-time = "2025-10-06T14:12:43.861Z" }, - { url = "https://files.pythonhosted.org/packages/8c/52/c49a619ee35a402fa3a7019a4fa8d26878fec0d1243f6968bbf516789578/yarl-1.22.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8", size = 350700, upload-time = "2025-10-06T14:12:46.868Z" }, - { url = "https://files.pythonhosted.org/packages/ab/c9/f5042d87777bf6968435f04a2bbb15466b2f142e6e47fa4f34d1a3f32f0c/yarl-1.22.0-cp39-cp39-win32.whl", hash = "sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b", size = 82323, upload-time = "2025-10-06T14:12:48.633Z" }, - { url = "https://files.pythonhosted.org/packages/fd/58/d00f7cad9eba20c4eefac2682f34661d1d1b3a942fc0092eb60e78cfb733/yarl-1.22.0-cp39-cp39-win_amd64.whl", hash = "sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed", size = 87145, upload-time = "2025-10-06T14:12:50.241Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a3/70904f365080780d38b919edd42d224b8c4ce224a86950d2eaa2a24366ad/yarl-1.22.0-cp39-cp39-win_arm64.whl", hash = "sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2", size = 82173, upload-time = "2025-10-06T14:12:51.869Z" }, - { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, -] - -[[package]] -name = "zipp" -version = "3.23.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, -] From b685f1081dc426b11202d87a4b01ff56dcbe02c0 Mon Sep 17 00:00:00 2001 From: scalarbot Date: Wed, 23 Sep 2026 20:06:50 +0000 Subject: [PATCH 2/6] feat(api)!: update auth scheme BearerAuth (+122 more changes) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Configuration of `bearer` auth scheme `BearerAuth` changed. - Removed header param `X-Dedalus-Org-Id` from `machines.list`. - Removed header param `X-Dedalus-Org-Id` from `machines.create`. - Removed header param `X-Dedalus-Org-Id` from `machines.retrieve`. - Removed header param `X-Dedalus-Org-Id` from `machines.update`. - Removed header param `X-Dedalus-Org-Id` from `machines.delete`. - Removed header param `X-Dedalus-Org-Id` from `machines.sleep`. - Removed header param `X-Dedalus-Org-Id` from `machines.wake`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.list`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.create`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.retrieve`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.delete`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.list`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.create`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.retrieve`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.delete`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.output`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.events`. - Serialization or defaults of path param `machine_id` on `machines.terminals.connect` changed. - Serialization or defaults of path param `terminal_id` on `machines.terminals.connect` changed. - Removed header param `X-Dedalus-Org-Id` from `machines.terminals.connect`. - Removed `401` error response from `machines.terminals.connect`. - Removed `403` error response from `machines.terminals.connect`. - Removed `409` error response from `machines.terminals.connect`. - Removed `429` error response from `machines.terminals.connect`. - Removed `503` error response from `machines.terminals.connect`. - Removed operation `machines.watch` (`GET /v1/machines/{machine_id}/status/stream`). - Removed operation `machines.network.retrieve` (`GET /v1/machines/{machine_id}/network`). - Removed operation `machines.artifacts.list` (`GET /v1/machines/{machine_id}/artifacts`). - Removed operation `machines.artifacts.retrieve` (`GET /v1/machines/{machine_id}/artifacts/{artifact_id}`). - Removed operation `machines.artifacts.delete` (`DELETE /v1/machines/{machine_id}/artifacts/{artifact_id}`). - Removed operation `machines.ports.list` (`GET /v1/machines/{machine_id}/ports`). - Removed operation `machines.ports.create` (`POST /v1/machines/{machine_id}/ports`). - Removed operation `machines.ports.retrieve` (`GET /v1/machines/{machine_id}/ports/{port_id}`). - Removed operation `machines.ports.delete` (`DELETE /v1/machines/{machine_id}/ports/{port_id}`). - Removed operation `machines.terminals.list` (`GET /v1/machines/{machine_id}/terminals`). - Removed operation `machines.terminals.create` (`POST /v1/machines/{machine_id}/terminals`). - Removed operation `machines.terminals.retrieve` (`GET /v1/machines/{machine_id}/terminals/{terminal_id}`). - Removed operation `machines.terminals.delete` (`DELETE /v1/machines/{machine_id}/terminals/{terminal_id}`). - Removed operation `networks.retrieve` (`GET /v1/networks/{network_id}`). - Removed operation `usage.retrieve` (`GET /v1/usage`). - Removed operation `usage.machineCompute` (`GET /v1/usage/machines/compute`). - Removed operation `usage.machineStorage` (`GET /v1/usage/machines/storage`). - Added optional property `execution.creation_request_id`. - Added optional property `execution.creation_trace_id`. - Added required property `execution.log_capture`. - Property `execution.machine_id` type changed from `string` to `string`. - Property `machine.machine_id` type changed from `string` to `string`. - Added optional property `lifecycle_status.memory_assigned_mib`. - Added required property `lifecycle_status.memory_configured_mib`. - Added optional property `lifecycle_status.memory_last_autoresized_at`. - Added optional property `lifecycle_status.memory_resize_state`. - Added optional property `lifecycle_status.memory_target_mib`. - Property `machine_detail_response.machine_id` type changed from `string` to `string`. - Added schema `machine_execution_log_capture`. - Schema `machine_id_path_segment` shape changed. - Property `machine_list_item.machine_id` type changed from `string` to `string`. - Property `ssh_session.machine_id` type changed from `string` to `string`. - Property `ssh_session.status` type changed from `enum(wake_in_progress | ready | closed | …)` to `enum(wake_in_progress | ssh_in_progress | ready | …)`. - Added optional property `CreateResponseHeaders.Idempotency-Key`. - Removed optional property `CreateResponseHeaders.ETag`. - Removed optional property `CreateResponseHeaders.X-Dedalus-Storage-Operation-Id`. - Added schema `CreateStatus401ResponseHeaders`. - Added schema `CreateStatus403ResponseHeaders`. - Added schema `CreateStatus409ResponseHeaders`. - Added schema `CreateStatus429ResponseHeaders`. - Added schema `CreateStatus503ResponseHeaders`. - Added schema `CreateStatusdefaultResponseHeaders`. - Added optional property `UpdateResponseHeaders.Idempotency-Key`. - Added optional property `UpdateResponseHeaders.Location`. - Added schema `UpdateStatus401ResponseHeaders`. - Added schema `UpdateStatus403ResponseHeaders`. - Added schema `UpdateStatus409ResponseHeaders`. - Added schema `UpdateStatus429ResponseHeaders`. - Added schema `UpdateStatus503ResponseHeaders`. - Added schema `UpdateStatusdefaultResponseHeaders`. - Added optional property `DeleteResponseHeaders.Idempotency-Key`. - Added optional property `DeleteResponseHeaders.Location`. - Added schema `DeleteStatus401ResponseHeaders`. - Added schema `DeleteStatus403ResponseHeaders`. - Added schema `DeleteStatus409ResponseHeaders`. - Added schema `DeleteStatus429ResponseHeaders`. - Added schema `DeleteStatus503ResponseHeaders`. - Added schema `DeleteStatusdefaultResponseHeaders`. - Added optional property `SleepResponseHeaders.Idempotency-Key`. - Added optional property `SleepResponseHeaders.Location`. - Added schema `SleepStatus401ResponseHeaders`. - Added schema `SleepStatus403ResponseHeaders`. - Added schema `SleepStatus409ResponseHeaders`. - Added schema `SleepStatus429ResponseHeaders`. - Added schema `SleepStatus503ResponseHeaders`. - Added schema `SleepStatusdefaultResponseHeaders`. - Added optional property `WakeResponseHeaders.Idempotency-Key`. - Added optional property `WakeResponseHeaders.Location`. - Added schema `WakeStatus401ResponseHeaders`. - Added schema `WakeStatus403ResponseHeaders`. - Added schema `WakeStatus409ResponseHeaders`. - Added schema `WakeStatus429ResponseHeaders`. - Added schema `WakeStatus503ResponseHeaders`. - Added schema `WakeStatusdefaultResponseHeaders`. - Removed schema `artifact_list`. - Removed schema `artifact`. - Removed schema `port_create_params`. - Removed schema `terminal_create_params`. - Removed schema `machine_compute_usage`. - Removed schema `machine_compute_usage_row`. - Removed schema `machine_network`. - Removed schema `machine_storage_usage`. - Removed schema `machine_storage_usage_row`. - Removed schema `network_gateway`. - Removed schema `network`. - Removed schema `port_list`. - Removed schema `port`. - Removed schema `terminal_client_event`. - Removed schema `terminal_closed_event`. - Removed schema `terminal_error_event`. - Removed schema `terminal_input_event`. - Removed schema `terminal_list`. - Removed schema `terminal_output_event`. - Removed schema `terminal_resize_event`. - Removed schema `terminal`. - Removed schema `terminal_server_event`. - Removed schema `org_usage`. BREAKING CHANGE: 72 breaking changes to the SDK surface. - Configuration of `bearer` auth scheme `BearerAuth` changed. - Removed header param `X-Dedalus-Org-Id` from `machines.list`. - Removed header param `X-Dedalus-Org-Id` from `machines.create`. - Removed header param `X-Dedalus-Org-Id` from `machines.retrieve`. - Removed header param `X-Dedalus-Org-Id` from `machines.update`. - Removed header param `X-Dedalus-Org-Id` from `machines.delete`. - Removed header param `X-Dedalus-Org-Id` from `machines.sleep`. - Removed header param `X-Dedalus-Org-Id` from `machines.wake`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.list`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.create`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.retrieve`. - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.delete`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.list`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.create`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.retrieve`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.delete`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.output`. - Removed header param `X-Dedalus-Org-Id` from `machines.executions.events`. - Serialization or defaults of path param `machine_id` on `machines.terminals.connect` changed. - Serialization or defaults of path param `terminal_id` on `machines.terminals.connect` changed. - Removed header param `X-Dedalus-Org-Id` from `machines.terminals.connect`. - Removed operation `machines.watch` (`GET /v1/machines/{machine_id}/status/stream`). - Removed operation `machines.network.retrieve` (`GET /v1/machines/{machine_id}/network`). - Removed operation `machines.artifacts.list` (`GET /v1/machines/{machine_id}/artifacts`). - Removed operation `machines.artifacts.retrieve` (`GET /v1/machines/{machine_id}/artifacts/{artifact_id}`). - Removed operation `machines.artifacts.delete` (`DELETE /v1/machines/{machine_id}/artifacts/{artifact_id}`). - Removed operation `machines.ports.list` (`GET /v1/machines/{machine_id}/ports`). - Removed operation `machines.ports.create` (`POST /v1/machines/{machine_id}/ports`). - Removed operation `machines.ports.retrieve` (`GET /v1/machines/{machine_id}/ports/{port_id}`). - Removed operation `machines.ports.delete` (`DELETE /v1/machines/{machine_id}/ports/{port_id}`). - Removed operation `machines.terminals.list` (`GET /v1/machines/{machine_id}/terminals`). - Removed operation `machines.terminals.create` (`POST /v1/machines/{machine_id}/terminals`). - Removed operation `machines.terminals.retrieve` (`GET /v1/machines/{machine_id}/terminals/{terminal_id}`). - Removed operation `machines.terminals.delete` (`DELETE /v1/machines/{machine_id}/terminals/{terminal_id}`). - Removed operation `networks.retrieve` (`GET /v1/networks/{network_id}`). - Removed operation `usage.retrieve` (`GET /v1/usage`). - Removed operation `usage.machineCompute` (`GET /v1/usage/machines/compute`). - Removed operation `usage.machineStorage` (`GET /v1/usage/machines/storage`). - Added required property `execution.log_capture`. - Property `execution.machine_id` type changed from `string` to `string`. - Property `machine.machine_id` type changed from `string` to `string`. - Added required property `lifecycle_status.memory_configured_mib`. - Property `machine_detail_response.machine_id` type changed from `string` to `string`. - Schema `machine_id_path_segment` shape changed. - Property `machine_list_item.machine_id` type changed from `string` to `string`. - Property `ssh_session.machine_id` type changed from `string` to `string`. - Property `ssh_session.status` type changed from `enum(wake_in_progress | ready | closed | …)` to `enum(wake_in_progress | ssh_in_progress | ready | …)`. - Removed optional property `CreateResponseHeaders.ETag`. - Removed optional property `CreateResponseHeaders.X-Dedalus-Storage-Operation-Id`. - Removed schema `artifact_list`. - Removed schema `artifact`. - Removed schema `port_create_params`. - Removed schema `terminal_create_params`. - Removed schema `machine_compute_usage`. - Removed schema `machine_compute_usage_row`. - Removed schema `machine_network`. - Removed schema `machine_storage_usage`. - Removed schema `machine_storage_usage_row`. - Removed schema `network_gateway`. - Removed schema `network`. - Removed schema `port_list`. - Removed schema `port`. - Removed schema `terminal_client_event`. - Removed schema `terminal_closed_event`. - Removed schema `terminal_error_event`. - Removed schema `terminal_input_event`. - Removed schema `terminal_list`. - Removed schema `terminal_output_event`. - Removed schema `terminal_resize_event`. - Removed schema `terminal`. - Removed schema `terminal_server_event`. - Removed schema `org_usage`. Build: 3GBYTz5OEOeRfZnsJPf6V --- .claude/skills/dedalus-python-sdk/SKILL.md | 15 +- README.md | 22 +- SKILL.md | 15 +- api.md | 290 +- scalar-sdk.manifest.json | 7240 +++++------------ src/dedalus_sdk/_client.py | 76 +- src/dedalus_sdk/_streaming.py | 48 +- src/dedalus_sdk/resources/__init__.py | 28 - .../resources/machines/__init__.py | 42 - .../resources/machines/artifacts.py | 432 - .../resources/machines/executions.py | 86 +- .../resources/machines/machines.py | 303 +- src/dedalus_sdk/resources/machines/network.py | 164 - src/dedalus_sdk/resources/machines/ports.py | 568 -- src/dedalus_sdk/resources/machines/ssh.py | 58 +- .../resources/machines/terminals/terminals.py | 537 +- .../resources/machines/terminals/ws.py | 38 +- src/dedalus_sdk/resources/networks.py | 164 - src/dedalus_sdk/resources/usage.py | 393 - src/dedalus_sdk/types/__init__.py | 10 - src/dedalus_sdk/types/lifecycle_status.py | 15 + .../types/machine_compute_usage.py | 24 - .../types/machine_compute_usage_row.py | 52 - .../types/machine_create_params.py | 6 +- src/dedalus_sdk/types/machine_list_params.py | 6 +- .../types/machine_storage_usage.py | 21 - .../types/machine_storage_usage_row.py | 31 - .../types/machine_update_params.py | 7 +- src/dedalus_sdk/types/machines/__init__.py | 25 +- src/dedalus_sdk/types/machines/artifact.py | 30 - .../types/machines/artifact_list.py | 15 - .../types/machines/artifact_list_params.py | 19 - .../types/machines/connect_client_event.py | 17 + .../machines/connect_client_event_param.py | 15 + .../types/machines/connect_server_event.py | 17 + src/dedalus_sdk/types/machines/execution.py | 18 +- .../types/machines/execution_create_params.py | 7 +- .../types/machines/execution_events_params.py | 7 +- .../types/machines/execution_list_params.py | 7 +- .../types/machines/machine_network.py | 19 - src/dedalus_sdk/types/machines/port.py | 35 - .../types/machines/port_create_params.py | 19 - src/dedalus_sdk/types/machines/port_list.py | 15 - .../types/machines/port_list_params.py | 19 - .../types/machines/ssh_create_params.py | 7 +- .../types/machines/ssh_list_params.py | 7 +- src/dedalus_sdk/types/machines/ssh_session.py | 2 +- src/dedalus_sdk/types/machines/terminal.py | 37 - .../types/machines/terminal_client_event.py | 15 - .../machines/terminal_client_event_param.py | 14 - .../types/machines/terminal_closed_event.py | 11 - .../types/machines/terminal_create_params.py | 26 - .../types/machines/terminal_error_event.py | 16 - .../types/machines/terminal_input_event.py | 14 - .../machines/terminal_input_event_param.py | 18 - .../types/machines/terminal_list.py | 15 - .../types/machines/terminal_list_params.py | 19 - .../types/machines/terminal_output_event.py | 14 - .../types/machines/terminal_resize_event.py | 15 - .../machines/terminal_resize_event_param.py | 15 - .../types/machines/terminal_server_event.py | 16 - src/dedalus_sdk/types/network.py | 17 - src/dedalus_sdk/types/network_gateway.py | 18 - src/dedalus_sdk/types/org_usage.py | 28 - .../types/usage_machine_compute_params.py | 21 - .../types/usage_machine_storage_params.py | 18 - .../types/usage_retrieve_params.py | 12 - tests/smoke-test.py | 845 +- 68 files changed, 2409 insertions(+), 9786 deletions(-) delete mode 100644 src/dedalus_sdk/resources/machines/artifacts.py delete mode 100644 src/dedalus_sdk/resources/machines/network.py delete mode 100644 src/dedalus_sdk/resources/machines/ports.py delete mode 100644 src/dedalus_sdk/resources/networks.py delete mode 100644 src/dedalus_sdk/resources/usage.py delete mode 100644 src/dedalus_sdk/types/machine_compute_usage.py delete mode 100644 src/dedalus_sdk/types/machine_compute_usage_row.py delete mode 100644 src/dedalus_sdk/types/machine_storage_usage.py delete mode 100644 src/dedalus_sdk/types/machine_storage_usage_row.py delete mode 100644 src/dedalus_sdk/types/machines/artifact.py delete mode 100644 src/dedalus_sdk/types/machines/artifact_list.py delete mode 100644 src/dedalus_sdk/types/machines/artifact_list_params.py create mode 100644 src/dedalus_sdk/types/machines/connect_client_event.py create mode 100644 src/dedalus_sdk/types/machines/connect_client_event_param.py create mode 100644 src/dedalus_sdk/types/machines/connect_server_event.py delete mode 100644 src/dedalus_sdk/types/machines/machine_network.py delete mode 100644 src/dedalus_sdk/types/machines/port.py delete mode 100644 src/dedalus_sdk/types/machines/port_create_params.py delete mode 100644 src/dedalus_sdk/types/machines/port_list.py delete mode 100644 src/dedalus_sdk/types/machines/port_list_params.py delete mode 100644 src/dedalus_sdk/types/machines/terminal.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_client_event.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_client_event_param.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_closed_event.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_create_params.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_error_event.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_input_event.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_input_event_param.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_list.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_list_params.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_output_event.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_resize_event.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_resize_event_param.py delete mode 100644 src/dedalus_sdk/types/machines/terminal_server_event.py delete mode 100644 src/dedalus_sdk/types/network.py delete mode 100644 src/dedalus_sdk/types/network_gateway.py delete mode 100644 src/dedalus_sdk/types/org_usage.py delete mode 100644 src/dedalus_sdk/types/usage_machine_compute_params.py delete mode 100644 src/dedalus_sdk/types/usage_machine_storage_params.py delete mode 100644 src/dedalus_sdk/types/usage_retrieve_params.py diff --git a/.claude/skills/dedalus-python-sdk/SKILL.md b/.claude/skills/dedalus-python-sdk/SKILL.md index 9f015db..7c0959a 100644 --- a/.claude/skills/dedalus-python-sdk/SKILL.md +++ b/.claude/skills/dedalus-python-sdk/SKILL.md @@ -28,7 +28,7 @@ client = Dedalus( Provide credentials using the options below. Environment variables are read automatically when the target runtime supports them: - `x_api_key` (env: `DEDALUS_X_API_KEY`) — API key authentication using X-API-Key header -- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key in Authorization: Bearer . +- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key or short-lived delegated access token in Authorization: Bearer . - `api_key` (env: `DEDALUS_API_KEY`) — API key authentication using Bearer token ## Calling operations @@ -63,19 +63,6 @@ List endpoints return paginated results you can iterate directly; the SDK fetche page = client.machines.list() ``` -## Streaming - -Streaming endpoints return an iterator that yields results as the server emits them. - -```python -stream = client.machines.watch( - machine_id="machineID", -) - -for machine in stream: - print(machine) -``` - ## WebSockets WebSocket endpoints open a persistent connection you can send messages to and receive messages from. diff --git a/README.md b/README.md index 37954ee..a7021b4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,6 @@ The full API of this library can be found in [api.md](./api.md). - [Usage](#usage) - [API Reference](./api.md) - [Async](#async) -- [Streaming](#streaming) - [WebSockets](#websockets) - [Authentication](#authentication) - [Errors](#errors) @@ -87,21 +86,6 @@ asyncio.run(main())
-## Streaming - -Streaming endpoints return an async iterator that yields results as the server emits them. - -```python -stream = client.machines.watch( - machine_id="machineID", -) - -for machine in stream: - print(machine) -``` - -
- ## WebSockets WebSocket endpoints open a persistent connection you can send messages to and receive messages from. @@ -121,7 +105,7 @@ Pass credentials to the generated client constructor. Environment variables are | Option | Type | Default | Description | | --- | --- | --- | --- | | `x_api_key` | `string \| provider` | - | API key authentication using X-API-Key header Defaults to DEDALUS_X_API_KEY. | -| `bearer_auth` | `string \| provider` | - | Dedalus API key in Authorization: Bearer . Defaults to DEDALUS_BEARER_AUTH. | +| `bearer_auth` | `string \| provider` | - | Dedalus API key or short-lived delegated access token in Authorization: Bearer . Defaults to DEDALUS_BEARER_AUTH. | | `api_key` | `string \| provider` | - | API key authentication using Bearer token Defaults to DEDALUS_API_KEY. | Declared schemes: @@ -152,7 +136,7 @@ except APIStatusError as err: raise ``` -Documented error statuses: `400`, `401`, `403`, `409`, `429`, `500`, `502`, `503`, `default`. +Documented error statuses: `401`, `403`, `409`, `429`, `503`, `default`.
@@ -172,7 +156,7 @@ client = Dedalus( | Option | Type | Default | Description | | --- | --- | --- | --- | | `x_api_key` | `str \| None` | `os.environ.get("DEDALUS_X_API_KEY")` | API key authentication using X-API-Key header | -| `bearer_auth` | `str \| None` | `os.environ.get("DEDALUS_BEARER_AUTH")` | Dedalus API key in Authorization: Bearer . | +| `bearer_auth` | `str \| None` | `os.environ.get("DEDALUS_BEARER_AUTH")` | Dedalus API key or short-lived delegated access token in Authorization: Bearer . | | `api_key` | `str \| None` | `os.environ.get("DEDALUS_API_KEY")` | API key authentication using Bearer token | | `base_url` | `str \| httpx.URL \| None` | - | Override the default API base URL. | | `timeout` | `float \| Timeout \| None` | `60.0` | Maximum time in seconds to wait for a response before aborting a request. | diff --git a/SKILL.md b/SKILL.md index 5b31453..1937012 100644 --- a/SKILL.md +++ b/SKILL.md @@ -28,7 +28,7 @@ client = Dedalus( Provide credentials using the options below. Environment variables are read automatically when the target runtime supports them: - `x_api_key` (env: `DEDALUS_X_API_KEY`) — API key authentication using X-API-Key header -- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key in Authorization: Bearer . +- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key or short-lived delegated access token in Authorization: Bearer . - `api_key` (env: `DEDALUS_API_KEY`) — API key authentication using Bearer token ## Calling operations @@ -63,19 +63,6 @@ List endpoints return paginated results you can iterate directly; the SDK fetche page = client.machines.list() ``` -## Streaming - -Streaming endpoints return an iterator that yields results as the server emits them. - -```python -stream = client.machines.watch( - machine_id="machineID", -) - -for machine in stream: - print(machine) -``` - ## WebSockets WebSocket endpoints open a persistent connection you can send messages to and receive messages from. diff --git a/api.md b/api.md index b2335ae..e7544cf 100644 --- a/api.md +++ b/api.md @@ -10,20 +10,8 @@ Complete reference of every operation, grouped by resource. See [the README](./R - [Get machine](#get-machine) - [Update machine](#update-machine) - [Destroy machine](#destroy-machine) - - [Watch machine lifecycle status](#watch-machine-lifecycle-status) - [Sleep a running machine](#sleep-a-running-machine) - [Wake a sleeping machine](#wake-a-sleeping-machine) - - [`Machines Network`](#machines-network) - - [Get machine network identity](#get-machine-network-identity) - - [`Machines Artifacts`](#machines-artifacts) - - [List artifacts](#list-artifacts) - - [Get artifact](#get-artifact) - - [Delete artifact](#delete-artifact) - - [`Machines Ports`](#machines-ports) - - [List ports](#list-ports) - - [Create port](#create-port) - - [Get port](#get-port) - - [Delete port](#delete-port) - [`Machines Ssh`](#machines-ssh) - [List SSH sessions](#list-ssh-sessions) - [Create SSH session](#create-ssh-session) @@ -37,17 +25,7 @@ Complete reference of every operation, grouped by resource. See [the README](./R - [Get execution output](#get-execution-output) - [List execution events](#list-execution-events) - [`Machines Terminals`](#machines-terminals) - - [List terminals](#list-terminals) - - [Create terminal](#create-terminal) - - [Get terminal](#get-terminal) - - [Delete terminal](#delete-terminal) - - [Connect to terminal WebSocket stream](#connect-to-terminal-websocket-stream) -- [`Networks`](#networks) - - [Get network details](#get-network-details) -- [`Usage`](#usage) - - [Get usage summary](#get-usage-summary) - - [List machine compute usage breakdown](#list-machine-compute-usage-breakdown) - - [List machine storage usage breakdown](#list-machine-storage-usage-breakdown) + - [`connect`](#connect) ## Setup @@ -98,7 +76,7 @@ machine = client.machines.create( ```python machine = client.machines.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` @@ -111,7 +89,7 @@ machine = client.machines.retrieve( ```python machine = client.machines.update( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` @@ -124,28 +102,11 @@ machine = client.machines.update( ```python machine = client.machines.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` -### Watch machine lifecycle status - -Streams machine lifecycle updates over Server-Sent Events. Each `status` event contains a full `LifecycleResponse` payload. The stream closes after the machine reaches its current desired state. - -| Direction | Type | -| --- | --- | -| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | - -```python -stream = client.machines.watch( - machine_id="machineID", -) - -for machine in stream: - print(machine) -``` - ### Sleep a running machine | Direction | Type | @@ -154,7 +115,7 @@ for machine in stream: ```python machine = client.machines.sleep( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` @@ -167,118 +128,7 @@ machine = client.machines.sleep( ```python machine = client.machines.wake( - machine_id="machineID", - idempotency_key="", -) -``` - -### `Machines Network` - -#### Get machine network identity - -| Direction | Type | -| --- | --- | -| Response | [`MachineNetwork`](./src/dedalus_sdk/types/machines/machine_network.py) | - -```python -network = client.machines.network.retrieve( - machine_id="machineID", -) -``` - -### `Machines Artifacts` - -#### List artifacts - -| Direction | Type | -| --- | --- | -| Request | [`ArtifactListParams`](./src/dedalus_sdk/types/machines/artifact_list_params.py) | - -```python -page = client.machines.artifacts.list( - machine_id="machineID", -) -``` - -#### Get artifact - -| Direction | Type | -| --- | --- | -| Response | [`Artifact`](./src/dedalus_sdk/types/machines/artifact.py) | - -```python -artifact = client.machines.artifacts.retrieve( - machine_id="machineID", - artifact_id="artifactID", -) -``` - -#### Delete artifact - -| Direction | Type | -| --- | --- | -| Response | [`Artifact`](./src/dedalus_sdk/types/machines/artifact.py) | - -```python -artifact = client.machines.artifacts.delete( - machine_id="machineID", - artifact_id="artifactID", - idempotency_key="", -) -``` - -### `Machines Ports` - -#### List ports - -| Direction | Type | -| --- | --- | -| Request | [`PortListParams`](./src/dedalus_sdk/types/machines/port_list_params.py) | - -```python -page = client.machines.ports.list( - machine_id="machineID", -) -``` - -#### Create port - -| Direction | Type | -| --- | --- | -| Request | [`PortCreateParams`](./src/dedalus_sdk/types/machines/port_create_params.py) | -| Response | [`Port`](./src/dedalus_sdk/types/machines/port.py) | - -```python -port = client.machines.ports.create( - machine_id="machineID", - port=0, - idempotency_key="", -) -``` - -#### Get port - -| Direction | Type | -| --- | --- | -| Response | [`Port`](./src/dedalus_sdk/types/machines/port.py) | - -```python -port = client.machines.ports.retrieve( - machine_id="machineID", - port_id="portID", -) -``` - -#### Delete port - -| Direction | Type | -| --- | --- | -| Response | [`Port`](./src/dedalus_sdk/types/machines/port.py) | - -```python -port = client.machines.ports.delete( - machine_id="machineID", - port_id="portID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` @@ -293,7 +143,7 @@ port = client.machines.ports.delete( ```python page = client.machines.ssh.list( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` @@ -306,7 +156,7 @@ page = client.machines.ssh.list( ```python ssh = client.machines.ssh.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", public_key="", idempotency_key="", ) @@ -320,7 +170,7 @@ ssh = client.machines.ssh.create( ```python ssh = client.machines.ssh.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", ) ``` @@ -333,7 +183,7 @@ ssh = client.machines.ssh.retrieve( ```python ssh = client.machines.ssh.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", idempotency_key="", ) @@ -349,7 +199,7 @@ ssh = client.machines.ssh.delete( ```python page = client.machines.executions.list( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` @@ -362,7 +212,7 @@ page = client.machines.executions.list( ```python execution = client.machines.executions.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", command=[""], idempotency_key="", ) @@ -376,7 +226,7 @@ execution = client.machines.executions.create( ```python execution = client.machines.executions.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -389,7 +239,7 @@ execution = client.machines.executions.retrieve( ```python execution = client.machines.executions.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", idempotency_key="", ) @@ -403,7 +253,7 @@ execution = client.machines.executions.delete( ```python execution = client.machines.executions.output( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -416,123 +266,17 @@ execution = client.machines.executions.output( ```python page = client.machines.executions.events( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` ### `Machines Terminals` -#### List terminals - -| Direction | Type | -| --- | --- | -| Request | [`TerminalListParams`](./src/dedalus_sdk/types/machines/terminal_list_params.py) | - -```python -page = client.machines.terminals.list( - machine_id="machineID", -) -``` - -#### Create terminal - -| Direction | Type | -| --- | --- | -| Request | [`TerminalCreateParams`](./src/dedalus_sdk/types/machines/terminal_create_params.py) | -| Response | [`Terminal`](./src/dedalus_sdk/types/machines/terminal.py) | - -```python -terminal = client.machines.terminals.create( - machine_id="machineID", - height=0, - width=0, - idempotency_key="", -) -``` - -#### Get terminal - -| Direction | Type | -| --- | --- | -| Response | [`Terminal`](./src/dedalus_sdk/types/machines/terminal.py) | - -```python -terminal = client.machines.terminals.retrieve( - machine_id="machineID", - terminal_id="terminalID", -) -``` - -#### Delete terminal - -| Direction | Type | -| --- | --- | -| Response | [`Terminal`](./src/dedalus_sdk/types/machines/terminal.py) | - -```python -terminal = client.machines.terminals.delete( - machine_id="machineID", - terminal_id="terminalID", - idempotency_key="", -) -``` - -#### Connect to terminal WebSocket stream - -Upgrades to a WebSocket connection for interactive terminal I/O. Clients send JSON `TerminalClientEvent` messages and receive JSON `TerminalServerEvent` messages. Terminal byte streams are base64-encoded inside `input` and `output` events; `resize` events use integer `width` and `height` fields. +#### `connect` ```python with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: message = connection.recv() print(message) ``` - -## `Networks` - -### Get network details - -| Direction | Type | -| --- | --- | -| Response | [`Network`](./src/dedalus_sdk/types/network.py) | - -```python -network = client.networks.retrieve( - network_id="networkID", -) -``` - -## `Usage` - -### Get usage summary - -| Direction | Type | -| --- | --- | -| Request | [`UsageRetrieveParams`](./src/dedalus_sdk/types/usage_retrieve_params.py) | -| Response | [`OrgUsage`](./src/dedalus_sdk/types/org_usage.py) | - -```python -usage = client.usage.retrieve() -``` - -### List machine compute usage breakdown - -| Direction | Type | -| --- | --- | -| Request | [`UsageMachineComputeParams`](./src/dedalus_sdk/types/usage_machine_compute_params.py) | -| Response | [`MachineComputeUsage`](./src/dedalus_sdk/types/machine_compute_usage.py) | - -```python -usage = client.usage.machine_compute() -``` - -### List machine storage usage breakdown - -| Direction | Type | -| --- | --- | -| Request | [`UsageMachineStorageParams`](./src/dedalus_sdk/types/usage_machine_storage_params.py) | -| Response | [`MachineStorageUsage`](./src/dedalus_sdk/types/machine_storage_usage.py) | - -```python -usage = client.usage.machine_storage() -``` diff --git a/scalar-sdk.manifest.json b/scalar-sdk.manifest.json index 0ea24f3..80b6af9 100644 --- a/scalar-sdk.manifest.json +++ b/scalar-sdk.manifest.json @@ -26,7 +26,7 @@ { "kind": "bearer", "id": "BearerAuth", - "bearerFormat": "Dedalus API key" + "bearerFormat": "Dedalus API key or delegated access token" }, { "kind": "bearer", @@ -35,49 +35,6 @@ ], "clientHeaderParams": [], "schemas": [ - { - "name": "artifact_list", - "source": "artifact_list", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "items", - "publicName": "items", - "required": true, - "deprecated": false, - "type": { - "kind": "union", - "variants": [ - { - "kind": "array", - "items": { - "kind": "ref", - "name": "artifact" - } - }, - { - "kind": "null" - } - ] - } - }, - { - "name": "next_cursor", - "publicName": "next_cursor", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - } - ], - "additionalProperties": false - } - }, { "name": "artifact_ref", "source": "artifact_ref", @@ -110,121 +67,6 @@ "additionalProperties": false } }, - { - "name": "artifact", - "source": "artifact", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "artifact_id", - "publicName": "artifact_id", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "created_at", - "publicName": "created_at", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "download_url", - "publicName": "download_url", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "execution_id", - "publicName": "execution_id", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "expires_at", - "publicName": "expires_at", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "machine_id", - "publicName": "machine_id", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "mime_type", - "publicName": "mime_type", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "name", - "publicName": "name", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "sha256", - "publicName": "sha256", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "size_bytes", - "publicName": "size_bytes", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - } - ], - "additionalProperties": false - } - }, { "name": "execution_create_params", "source": "execution_create_params", @@ -370,50 +212,6 @@ "additionalProperties": false } }, - { - "name": "port_create_params", - "source": "port_create_params", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "port", - "publicName": "port", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "protocol", - "publicName": "protocol", - "required": false, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "http", - "https" - ], - "names": [ - "HTTP", - "Https" - ], - "deprecations": [ - false, - false - ] - } - } - ], - "additionalProperties": false - } - }, { "name": "ssh_session_create_params", "source": "ssh_session_create_params", @@ -436,77 +234,6 @@ "additionalProperties": false } }, - { - "name": "terminal_create_params", - "source": "terminal_create_params", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "cwd", - "publicName": "cwd", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "env", - "publicName": "env", - "required": false, - "deprecated": false, - "type": { - "kind": "record", - "value": { - "kind": "primitive", - "type": "string" - }, - "propertyNames": { - "kind": "primitive", - "type": "string" - } - } - }, - { - "name": "height", - "publicName": "height", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "shell", - "publicName": "shell", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "width", - "publicName": "width", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - } - ], - "additionalProperties": false - } - }, { "name": "error_detail", "source": "error_detail", @@ -1053,8 +780,8 @@ } }, { - "name": "cwd", - "publicName": "cwd", + "name": "creation_request_id", + "publicName": "creation_request_id", "required": false, "deprecated": false, "type": { @@ -1063,19 +790,39 @@ } }, { - "name": "env_keys", - "publicName": "env_keys", + "name": "creation_trace_id", + "publicName": "creation_trace_id", "required": false, "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "array", - "items": { - "kind": "primitive", - "type": "string" - } + "kind": "primitive", + "type": "string" + } + }, + { + "name": "cwd", + "publicName": "cwd", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "env_keys", + "publicName": "env_keys", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "array", + "items": { + "kind": "primitive", + "type": "string" + } }, { "kind": "null" @@ -1135,6 +882,16 @@ "format": "date-time" } }, + { + "name": "log_capture", + "publicName": "log_capture", + "required": true, + "deprecated": false, + "type": { + "kind": "ref", + "name": "machine_execution_log_capture" + } + }, { "name": "machine_id", "publicName": "machine_id", @@ -1142,7 +899,8 @@ "deprecated": false, "type": { "kind": "primitive", - "type": "string" + "type": "string", + "format": "uuid" } }, { @@ -1314,7 +1072,8 @@ "deprecated": false, "type": { "kind": "primitive", - "type": "string" + "type": "string", + "format": "uuid" } }, { @@ -1436,6 +1195,83 @@ "format": "date-time" } }, + { + "name": "memory_assigned_mib", + "publicName": "memory_assigned_mib", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 1 + } + } + }, + { + "name": "memory_configured_mib", + "publicName": "memory_configured_mib", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 1 + } + } + }, + { + "name": "memory_last_autoresized_at", + "publicName": "memory_last_autoresized_at", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "memory_resize_state", + "publicName": "memory_resize_state", + "required": false, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "stable", + "error", + "pending_capacity" + ], + "names": [ + "Stable", + "Error", + "PendingCapacity" + ], + "deprecations": [ + false, + false, + false + ] + } + }, + { + "name": "memory_target_mib", + "publicName": "memory_target_mib", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 1 + } + } + }, { "name": "phase", "publicName": "phase", @@ -1513,81 +1349,66 @@ } }, { - "name": "machine_compute_usage", - "source": "machine_compute_usage", + "name": "machine_detail_response", + "source": "machine_detail_response", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "granularity", - "publicName": "granularity", + "name": "autosleep_seconds", + "publicName": "autosleep_seconds", "required": true, "deprecated": false, "type": { "kind": "primitive", - "type": "string" + "type": "integer", + "format": "int64", + "validation": { + "minimum": 0, + "maximum": 9223372036 + } } }, { - "name": "period_end", - "publicName": "period_end", + "name": "desired_state", + "publicName": "desired_state", "required": true, "deprecated": false, "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" + "kind": "enum", + "values": [ + "running", + "sleeping", + "destroyed" + ], + "names": [ + "Running", + "Sleeping", + "Destroyed" + ], + "deprecations": [ + false, + false, + false + ] } }, { - "name": "period_start", - "publicName": "period_start", + "name": "machine_id", + "publicName": "machine_id", "required": true, "deprecated": false, "type": { "kind": "primitive", "type": "string", - "format": "date-time" + "format": "uuid" } }, { - "name": "rows", - "publicName": "rows", - "required": true, - "deprecated": false, - "type": { - "kind": "union", - "variants": [ - { - "kind": "array", - "items": { - "kind": "ref", - "name": "machine_compute_usage_row" - } - }, - { - "kind": "null" - } - ] - } - } - ], - "additionalProperties": false - } - }, - { - "name": "machine_compute_usage_row", - "source": "machine_compute_usage_row", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "awake_seconds", - "publicName": "awake_seconds", + "name": "memory_mib", + "publicName": "memory_mib", "required": true, "deprecated": false, "type": { @@ -1597,290 +1418,147 @@ } }, { - "name": "bucket_end", - "publicName": "bucket_end", + "name": "status", + "publicName": "status", "required": true, "deprecated": false, "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" + "kind": "ref", + "name": "lifecycle_status" } }, { - "name": "bucket_start", - "publicName": "bucket_start", + "name": "storage_gib", + "publicName": "storage_gib", "required": true, "deprecated": false, "type": { "kind": "primitive", - "type": "string", - "format": "date-time" + "type": "integer", + "format": "int64" } }, { - "name": "cpu_millicore_seconds", - "publicName": "cpu_millicore_seconds", + "name": "vcpu", + "publicName": "vcpu", "required": true, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "number", + "format": "double" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_execution_log_capture", + "source": "machine_execution_log_capture", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "last_window_end", - "publicName": "last_window_end", - "required": true, + "name": "code", + "publicName": "code", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "string", - "format": "date-time" + "type": "string" } }, { - "name": "latest_meter_emitted_at", - "publicName": "latest_meter_emitted_at", + "name": "lost_bytes", + "publicName": "lost_bytes", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string", - "format": "date-time" + "validation": { + "pattern": "^(0|[1-9][0-9]*)$", + "maxLength": 20 + } } }, { - "name": "machine_id", - "publicName": "machine_id", - "required": true, + "name": "state", + "publicName": "state", + "required": false, "deprecated": false, "type": { - "kind": "primitive", - "type": "string" + "kind": "enum", + "values": [ + "pending", + "incomplete", + "unavailable" + ], + "names": [ + "Pending", + "Incomplete", + "Unavailable" + ], + "deprecations": [ + false, + false, + false + ] } }, { - "name": "memory_mib_seconds", - "publicName": "memory_mib_seconds", - "required": true, + "name": "unconfirmed_bytes", + "publicName": "unconfirmed_bytes", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "string", + "validation": { + "pattern": "^(0|[1-9][0-9]*)$", + "maxLength": 20 + } } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "machine_id_path_segment", + "source": "machine_id_path_segment", + "publicAliases": [], + "deprecated": false, + "extensions": { + "source": [ + "examples" + ], + "examples": "017f22e2-79b0-7cc3-98c4-dc0c0c07398f" + }, + "type": { + "kind": "primitive", + "type": "string", + "validation": { + "pattern": "^(dm-)?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "minLength": 36, + "maxLength": 39 + } + } + }, + { + "name": "machine_list_item", + "source": "machine_list_item", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "org_metering_bucket_ids", - "publicName": "org_metering_bucket_ids", - "required": true, - "deprecated": false, - "type": { - "kind": "union", - "variants": [ - { - "kind": "array", - "items": { - "kind": "primitive", - "type": "string" - } - }, - { - "kind": "null" - } - ] - } - }, - { - "name": "requested_memory_mib", - "publicName": "requested_memory_mib", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int32" - } - }, - { - "name": "requested_storage_gib", - "publicName": "requested_storage_gib", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int32" - } - }, - { - "name": "requested_vcpu", - "publicName": "requested_vcpu", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "number", - "format": "double" - } - }, - { - "name": "spec_fingerprint", - "publicName": "spec_fingerprint", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "window_count", - "publicName": "window_count", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - } - ], - "additionalProperties": false - } - }, - { - "name": "machine_detail_response", - "source": "machine_detail_response", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "autosleep_seconds", - "publicName": "autosleep_seconds", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64", - "validation": { - "minimum": 0, - "maximum": 9223372036 - } - } - }, - { - "name": "desired_state", - "publicName": "desired_state", - "required": true, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "running", - "sleeping", - "destroyed" - ], - "names": [ - "Running", - "Sleeping", - "Destroyed" - ], - "deprecations": [ - false, - false, - false - ] - } - }, - { - "name": "machine_id", - "publicName": "machine_id", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "memory_mib", - "publicName": "memory_mib", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "status", - "publicName": "status", - "required": true, - "deprecated": false, - "type": { - "kind": "ref", - "name": "lifecycle_status" - } - }, - { - "name": "storage_gib", - "publicName": "storage_gib", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "vcpu", - "publicName": "vcpu", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "number", - "format": "double" - } - } - ], - "additionalProperties": false - } - }, - { - "name": "machine_id_path_segment", - "source": "machine_id_path_segment", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "validation": { - "pattern": "^dm-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", - "minLength": 4, - "maxLength": 253 - } - } - }, - { - "name": "machine_list_item", - "source": "machine_list_item", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "autosleep_seconds", - "publicName": "autosleep_seconds", + "name": "autosleep_seconds", + "publicName": "autosleep_seconds", "required": true, "deprecated": false, "type": { @@ -1935,7 +1613,8 @@ "deprecated": false, "type": { "kind": "primitive", - "type": "string" + "type": "string", + "format": "uuid" } }, { @@ -2061,26 +1740,31 @@ } }, { - "name": "machine_network", - "source": "machine_network", + "name": "public_path_segment", + "source": "public_path_segment", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "validation": { + "pattern": "^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$", + "minLength": 1, + "maxLength": 253 + } + } + }, + { + "name": "ssh_connection", + "source": "ssh_connection", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "hostname", - "publicName": "hostname", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "machine_id", - "publicName": "machine_id", + "name": "endpoint", + "publicName": "endpoint", "required": true, "deprecated": false, "type": { @@ -2089,28 +1773,29 @@ } }, { - "name": "network_id", - "publicName": "network_id", - "required": true, + "name": "host_trust", + "publicName": "host_trust", + "required": false, "deprecated": false, "type": { - "kind": "primitive", - "type": "string" + "kind": "ref", + "name": "ssh_host_trust" } }, { - "name": "network_name", - "publicName": "network_name", + "name": "port", + "publicName": "port", "required": true, "deprecated": false, "type": { "kind": "primitive", - "type": "string" + "type": "integer", + "format": "int64" } }, { - "name": "private_ipv4", - "publicName": "private_ipv4", + "name": "ssh_username", + "publicName": "ssh_username", "required": true, "deprecated": false, "type": { @@ -2119,9 +1804,9 @@ } }, { - "name": "private_ipv6", - "publicName": "private_ipv6", - "required": true, + "name": "user_certificate", + "publicName": "user_certificate", + "required": false, "deprecated": false, "type": { "kind": "primitive", @@ -2133,268 +1818,44 @@ } }, { - "name": "machine_storage_usage", - "source": "machine_storage_usage", + "name": "ssh_host_trust", + "source": "ssh_host_trust", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "period_end", - "publicName": "period_end", + "name": "host_pattern", + "publicName": "host_pattern", "required": true, "deprecated": false, "type": { "kind": "primitive", - "type": "string", - "format": "date-time" + "type": "string" } }, { - "name": "period_start", - "publicName": "period_start", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "rows", - "publicName": "rows", - "required": true, - "deprecated": false, - "type": { - "kind": "union", - "variants": [ - { - "kind": "array", - "items": { - "kind": "ref", - "name": "machine_storage_usage_row" - } - }, - { - "kind": "null" - } - ] - } - } - ], - "additionalProperties": false - } - }, - { - "name": "machine_storage_usage_row", - "source": "machine_storage_usage_row", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "bucket_end", - "publicName": "bucket_end", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "bucket_start", - "publicName": "bucket_start", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "latest_meter_emitted_at", - "publicName": "latest_meter_emitted_at", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "logical_storage_bytes", - "publicName": "logical_storage_bytes", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "machine_id", - "publicName": "machine_id", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "org_metering_bucket_id", - "publicName": "org_metering_bucket_id", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "storage_mib_seconds", - "publicName": "storage_mib_seconds", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - } - ], - "additionalProperties": false - } - }, - { - "name": "network_gateway", - "source": "network_gateway", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "hostname", - "publicName": "hostname", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "kind", - "publicName": "kind", - "required": true, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "ssh", - "port" - ], - "names": [ - "Ssh", - "Port" - ], - "deprecations": [ - false, - false - ] - } - }, - { - "name": "port", - "publicName": "port", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64", - "validation": { - "minimum": 1, - "maximum": 65535 - } - } - }, - { - "name": "protocol", - "publicName": "protocol", + "name": "kind", + "publicName": "kind", "required": true, "deprecated": false, "type": { "kind": "enum", "values": [ - "ssh", - "https" + "cert_authority" ], "names": [ - "Ssh", - "Https" + "CertAuthority" ], "deprecations": [ - false, false ] } - } - ], - "additionalProperties": false - } - }, - { - "name": "network", - "source": "network", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "gateways", - "publicName": "gateways", - "required": true, - "deprecated": false, - "type": { - "kind": "union", - "variants": [ - { - "kind": "array", - "items": { - "kind": "ref", - "name": "network_gateway" - } - }, - { - "kind": "null" - } - ] - } - }, - { - "name": "name", - "publicName": "name", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } }, { - "name": "network_id", - "publicName": "network_id", + "name": "public_key", + "publicName": "public_key", "required": true, "deprecated": false, "type": { @@ -2407,8 +1868,8 @@ } }, { - "name": "port_list", - "source": "port_list", + "name": "ssh_session_list", + "source": "ssh_session_list", "publicAliases": [], "deprecated": false, "type": { @@ -2426,7 +1887,7 @@ "kind": "array", "items": { "kind": "ref", - "name": "port" + "name": "ssh_session" } }, { @@ -2450,13 +1911,23 @@ } }, { - "name": "port", - "source": "port", + "name": "ssh_session", + "source": "ssh_session", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ + { + "name": "connection", + "publicName": "connection", + "required": false, + "deprecated": false, + "type": { + "kind": "ref", + "name": "ssh_connection" + } + }, { "name": "created_at", "publicName": "created_at", @@ -2506,49 +1977,8 @@ "deprecated": false, "type": { "kind": "primitive", - "type": "string" - } - }, - { - "name": "port", - "publicName": "port", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "port_id", - "publicName": "port_id", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "protocol", - "publicName": "protocol", - "required": false, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "http", - "https" - ], - "names": [ - "HTTP", - "Https" - ], - "deprecations": [ - false, - false - ] + "type": "string", + "format": "uuid" } }, { @@ -2573,6 +2003,16 @@ "format": "int64" } }, + { + "name": "session_id", + "publicName": "session_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, { "name": "status", "publicName": "status", @@ -2582,6 +2022,7 @@ "kind": "enum", "values": [ "wake_in_progress", + "ssh_in_progress", "ready", "closed", "expired", @@ -2589,6 +2030,7 @@ ], "names": [ "WakeInProgress", + "SshInProgress", "Ready", "Closed", "Expired", @@ -2599,51 +2041,27 @@ false, false, false, + false, false ] } - }, - { - "name": "url", - "publicName": "url", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } } ], "additionalProperties": false } }, { - "name": "public_path_segment", - "source": "public_path_segment", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "validation": { - "pattern": "^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$", - "minLength": 1, - "maxLength": 253 - } - } - }, - { - "name": "ssh_connection", - "source": "ssh_connection", + "name": "update_params", + "source": "update_params", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "endpoint", - "publicName": "endpoint", - "required": true, + "name": "autosleep", + "publicName": "autosleep", + "required": false, "deprecated": false, "type": { "kind": "primitive", @@ -2651,20 +2069,10 @@ } }, { - "name": "host_trust", - "publicName": "host_trust", + "name": "memory_mib", + "publicName": "memory_mib", "required": false, "deprecated": false, - "type": { - "kind": "ref", - "name": "ssh_host_trust" - } - }, - { - "name": "port", - "publicName": "port", - "required": true, - "deprecated": false, "type": { "kind": "primitive", "type": "integer", @@ -2672,23 +2080,25 @@ } }, { - "name": "ssh_username", - "publicName": "ssh_username", - "required": true, + "name": "storage_gib", + "publicName": "storage_gib", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "string" + "type": "integer", + "format": "int64" } }, { - "name": "user_certificate", - "publicName": "user_certificate", + "name": "vcpu", + "publicName": "vcpu", "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "string" + "type": "number", + "format": "double" } } ], @@ -2696,17 +2106,17 @@ } }, { - "name": "ssh_host_trust", - "source": "ssh_host_trust", + "name": "CreateResponseHeaders", + "source": "CreateResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "host_pattern", - "publicName": "host_pattern", - "required": true, + "name": "ETag", + "publicName": "ETag", + "required": false, "deprecated": false, "type": { "kind": "primitive", @@ -2714,112 +2124,58 @@ } }, { - "name": "kind", - "publicName": "kind", - "required": true, + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, "deprecated": false, "type": { - "kind": "enum", - "values": [ - "cert_authority" - ], - "names": [ - "CertAuthority" - ], - "deprecations": [ - false - ] + "kind": "primitive", + "type": "string" } }, { - "name": "public_key", - "publicName": "public_key", - "required": true, + "name": "Location", + "publicName": "Location", + "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - } - ], - "additionalProperties": false - } - }, - { - "name": "ssh_session_list", - "source": "ssh_session_list", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ + }, { - "name": "items", - "publicName": "items", - "required": true, + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, "deprecated": false, "type": { "kind": "union", "variants": [ { - "kind": "array", - "items": { - "kind": "ref", - "name": "ssh_session" - } + "kind": "primitive", + "type": "string" }, { "kind": "null" } ] } - }, - { - "name": "next_cursor", - "publicName": "next_cursor", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } } ], "additionalProperties": false } }, { - "name": "ssh_session", - "source": "ssh_session", + "name": "CreateResponseHeaders", + "source": "CreateResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "connection", - "publicName": "connection", - "required": false, - "deprecated": false, - "type": { - "kind": "ref", - "name": "ssh_connection" - } - }, - { - "name": "created_at", - "publicName": "created_at", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "error_code", - "publicName": "error_code", + "name": "ETag", + "publicName": "ETag", "required": false, "deprecated": false, "type": { @@ -2828,8 +2184,8 @@ } }, { - "name": "error_message", - "publicName": "error_message", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { @@ -2838,146 +2194,97 @@ } }, { - "name": "expires_at", - "publicName": "expires_at", + "name": "Location", + "publicName": "Location", "required": false, "deprecated": false, - "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" - } - }, - { - "name": "machine_id", - "publicName": "machine_id", - "required": true, - "deprecated": false, "type": { "kind": "primitive", "type": "string" } }, { - "name": "ready_at", - "publicName": "ready_at", + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", "required": false, "deprecated": false, "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus401ResponseHeaders", + "source": "CreateStatus401ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "retry_after_ms", - "publicName": "retry_after_ms", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "session_id", - "publicName": "session_id", - "required": true, - "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, - { - "name": "status", - "publicName": "status", - "required": true, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "wake_in_progress", - "ready", - "closed", - "expired", - "failed" - ], - "names": [ - "WakeInProgress", - "Ready", - "Closed", - "Expired", - "Failed" - ], - "deprecations": [ - false, - false, - false, - false, - false - ] - } } ], "additionalProperties": false } }, { - "name": "terminal_client_event", - "source": "terminal_client_event", + "name": "CreateStatus403ResponseHeaders", + "source": "CreateStatus403ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "ref", - "name": "terminal_input_event" - }, + "kind": "object", + "properties": [ { - "kind": "ref", - "name": "terminal_resize_event" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } } ], - "discriminator": { - "propertyName": "type", - "mapping": { - "input": "terminal_input_event", - "resize": "terminal_resize_event" - } - }, - "variantNames": [ - null, - null - ] + "additionalProperties": false } }, { - "name": "terminal_closed_event", - "source": "terminal_closed_event", + "name": "CreateStatus409ResponseHeaders", + "source": "CreateStatus409ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "type", - "publicName": "type", - "required": true, + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, "deprecated": false, "type": { - "kind": "enum", - "values": [ - "closed" - ], - "names": [ - "Closed" - ], - "deprecations": [ - false - ] + "kind": "primitive", + "type": "string" } } ], @@ -2985,90 +2292,43 @@ } }, { - "name": "terminal_error_event", - "source": "terminal_error_event", + "name": "CreateStatus429ResponseHeaders", + "source": "CreateStatus429ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "error_code", - "publicName": "error_code", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "error_message", - "publicName": "error_message", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, - { - "name": "type", - "publicName": "type", - "required": true, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "error" - ], - "names": [ - "Error" - ], - "deprecations": [ - false - ] - } } ], "additionalProperties": false } }, { - "name": "terminal_input_event", - "source": "terminal_input_event", + "name": "CreateStatus503ResponseHeaders", + "source": "CreateStatus503ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "data", - "publicName": "data", - "required": true, + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "string", - "format": "byte" - } - }, - { - "name": "type", - "publicName": "type", - "required": true, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "input" - ], - "names": [ - "Input" - ], - "deprecations": [ - false - ] + "type": "string" } } ], @@ -3076,37 +2336,16 @@ } }, { - "name": "terminal_list", - "source": "terminal_list", + "name": "CreateStatusdefaultResponseHeaders", + "source": "CreateStatusdefaultResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "items", - "publicName": "items", - "required": true, - "deprecated": false, - "type": { - "kind": "union", - "variants": [ - { - "kind": "array", - "items": { - "kind": "ref", - "name": "terminal" - } - }, - { - "kind": "null" - } - ] - } - }, - { - "name": "next_cursor", - "publicName": "next_cursor", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { @@ -3119,40 +2358,21 @@ } }, { - "name": "terminal_output_event", - "source": "terminal_output_event", + "name": "RetrieveResponseHeaders", + "source": "RetrieveResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "data", - "publicName": "data", - "required": true, + "name": "ETag", + "publicName": "ETag", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "string", - "format": "byte" - } - }, - { - "name": "type", - "publicName": "type", - "required": true, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "output" - ], - "names": [ - "Output" - ], - "deprecations": [ - false - ] + "type": "string" } } ], @@ -3160,51 +2380,59 @@ } }, { - "name": "terminal_resize_event", - "source": "terminal_resize_event", + "name": "UpdateResponseHeaders", + "source": "UpdateResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "height", - "publicName": "height", - "required": true, + "name": "ETag", + "publicName": "ETag", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "string" } }, { - "name": "type", - "publicName": "type", - "required": true, + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, "deprecated": false, "type": { - "kind": "enum", - "values": [ - "resize" - ], - "names": [ - "Resize" - ], - "deprecations": [ - false - ] + "kind": "primitive", + "type": "string" } }, { - "name": "width", - "publicName": "width", - "required": true, + "name": "Location", + "publicName": "Location", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] } } ], @@ -3212,27 +2440,26 @@ } }, { - "name": "terminal", - "source": "terminal", + "name": "UpdateResponseHeaders", + "source": "UpdateResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "created_at", - "publicName": "created_at", - "required": true, + "name": "ETag", + "publicName": "ETag", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "string", - "format": "date-time" + "type": "string" } }, { - "name": "error_code", - "publicName": "error_code", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { @@ -3241,8 +2468,8 @@ } }, { - "name": "error_message", - "publicName": "error_message", + "name": "Location", + "publicName": "Location", "required": false, "deprecated": false, "type": { @@ -3251,189 +2478,170 @@ } }, { - "name": "expires_at", - "publicName": "expires_at", + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", "required": false, "deprecated": false, "type": { - "kind": "primitive", - "type": "string", - "format": "date-time" + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "UpdateStatus401ResponseHeaders", + "source": "UpdateStatus401ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "height", - "publicName": "height", - "required": true, + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "UpdateStatus403ResponseHeaders", + "source": "UpdateStatus403ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "machine_id", - "publicName": "machine_id", - "required": true, + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "UpdateStatus409ResponseHeaders", + "source": "UpdateStatus409ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "protocol", - "publicName": "protocol", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { - "kind": "enum", - "values": [ - "websocket" - ], - "names": [ - "Websocket" - ], - "deprecations": [ - false - ] + "kind": "primitive", + "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "UpdateStatus429ResponseHeaders", + "source": "UpdateStatus429ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "ready_at", - "publicName": "ready_at", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "string", - "format": "date-time" + "type": "string" } - }, - { - "name": "retry_after_ms", - "publicName": "retry_after_ms", - "required": false, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "status", - "publicName": "status", - "required": true, - "deprecated": false, - "type": { - "kind": "enum", - "values": [ - "wake_in_progress", - "ready", - "closed", - "expired", - "failed" - ], - "names": [ - "WakeInProgress", - "Ready", - "Closed", - "Expired", - "Failed" - ], - "deprecations": [ - false, - false, - false, - false, - false - ] - } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "UpdateStatus503ResponseHeaders", + "source": "UpdateStatus503ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "stream_url", - "publicName": "stream_url", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, - { - "name": "terminal_id", - "publicName": "terminal_id", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "string" - } - }, - { - "name": "width", - "publicName": "width", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } } ], "additionalProperties": false } }, { - "name": "terminal_server_event", - "source": "terminal_server_event", + "name": "UpdateStatusdefaultResponseHeaders", + "source": "UpdateStatusdefaultResponseHeaders", "publicAliases": [], "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "ref", - "name": "terminal_output_event" - }, - { - "kind": "ref", - "name": "terminal_error_event" - }, + "kind": "object", + "properties": [ { - "kind": "ref", - "name": "terminal_closed_event" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } } ], - "discriminator": { - "propertyName": "type", - "mapping": { - "closed": "terminal_closed_event", - "error": "terminal_error_event", - "output": "terminal_output_event" - } - }, - "variantNames": [ - null, - null, - null - ] + "additionalProperties": false } }, { - "name": "update_params", - "source": "update_params", + "name": "DeleteResponseHeaders", + "source": "DeleteResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "autosleep", - "publicName": "autosleep", + "name": "ETag", + "publicName": "ETag", "required": false, "deprecated": false, "type": { @@ -3442,36 +2650,41 @@ } }, { - "name": "memory_mib", - "publicName": "memory_mib", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "string" } }, { - "name": "storage_gib", - "publicName": "storage_gib", + "name": "Location", + "publicName": "Location", "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "string" } }, { - "name": "vcpu", - "publicName": "vcpu", + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", "required": false, "deprecated": false, "type": { - "kind": "primitive", - "type": "number", - "format": "double" + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] } } ], @@ -3479,72 +2692,27 @@ } }, { - "name": "org_usage", - "source": "org_usage", + "name": "DeleteResponseHeaders", + "source": "DeleteResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "billed_awake_seconds", - "publicName": "billed_awake_seconds", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "billed_cpu_millicore_seconds", - "publicName": "billed_cpu_millicore_seconds", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "billed_logical_storage_mib_seconds", - "publicName": "billed_logical_storage_mib_seconds", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "billed_memory_mib_seconds", - "publicName": "billed_memory_mib_seconds", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - }, - { - "name": "included_storage_gib", - "publicName": "included_storage_gib", - "required": true, + "name": "ETag", + "publicName": "ETag", + "required": false, "deprecated": false, "type": { "kind": "primitive", - "type": "integer", - "format": "int64" + "type": "string" } }, { - "name": "plan_slug", - "publicName": "plan_slug", - "required": true, + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, "deprecated": false, "type": { "kind": "primitive", @@ -3552,31 +2720,8 @@ } }, { - "name": "provisioned_storage_gib", - "publicName": "provisioned_storage_gib", - "required": true, - "deprecated": false, - "type": { - "kind": "primitive", - "type": "integer", - "format": "int64" - } - } - ], - "additionalProperties": false - } - }, - { - "name": "CreateResponseHeaders", - "source": "CreateResponseHeaders", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ - { - "name": "ETag", - "publicName": "ETag", + "name": "Location", + "publicName": "Location", "required": false, "deprecated": false, "type": { @@ -3607,39 +2752,43 @@ } }, { - "name": "CreateResponseHeaders", - "source": "CreateResponseHeaders", + "name": "DeleteStatus401ResponseHeaders", + "source": "DeleteStatus401ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "ETag", - "publicName": "ETag", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "DeleteStatus403ResponseHeaders", + "source": "DeleteStatus403ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "X-Dedalus-Storage-Operation-Id", - "publicName": "X-Dedalus-Storage-Operation-Id", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "primitive", - "type": "string" - }, - { - "kind": "null" - } - ] + "kind": "primitive", + "type": "string" } } ], @@ -3647,16 +2796,16 @@ } }, { - "name": "RetrieveResponseHeaders", - "source": "RetrieveResponseHeaders", + "name": "DeleteStatus409ResponseHeaders", + "source": "DeleteStatus409ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "ETag", - "publicName": "ETag", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { @@ -3669,39 +2818,43 @@ } }, { - "name": "UpdateResponseHeaders", - "source": "UpdateResponseHeaders", + "name": "DeleteStatus429ResponseHeaders", + "source": "DeleteStatus429ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "ETag", - "publicName": "ETag", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "DeleteStatus503ResponseHeaders", + "source": "DeleteStatus503ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "X-Dedalus-Storage-Operation-Id", - "publicName": "X-Dedalus-Storage-Operation-Id", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "primitive", - "type": "string" - }, - { - "kind": "null" - } - ] + "kind": "primitive", + "type": "string" } } ], @@ -3709,23 +2862,65 @@ } }, { - "name": "UpdateResponseHeaders", - "source": "UpdateResponseHeaders", + "name": "DeleteStatusdefaultResponseHeaders", + "source": "DeleteStatusdefaultResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "ETag", - "publicName": "ETag", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "SleepResponseHeaders", + "source": "SleepResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "Location", + "publicName": "Location", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, { "name": "X-Dedalus-Storage-Operation-Id", "publicName": "X-Dedalus-Storage-Operation-Id", @@ -3749,8 +2944,8 @@ } }, { - "name": "DeleteResponseHeaders", - "source": "DeleteResponseHeaders", + "name": "SleepResponseHeaders", + "source": "SleepResponseHeaders", "publicAliases": [], "deprecated": false, "type": { @@ -3766,6 +2961,26 @@ "type": "string" } }, + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "Location", + "publicName": "Location", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, { "name": "X-Dedalus-Storage-Operation-Id", "publicName": "X-Dedalus-Storage-Operation-Id", @@ -3789,39 +3004,43 @@ } }, { - "name": "DeleteResponseHeaders", - "source": "DeleteResponseHeaders", + "name": "SleepStatus401ResponseHeaders", + "source": "SleepStatus401ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "ETag", - "publicName": "ETag", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "SleepStatus403ResponseHeaders", + "source": "SleepStatus403ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "X-Dedalus-Storage-Operation-Id", - "publicName": "X-Dedalus-Storage-Operation-Id", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "primitive", - "type": "string" - }, - { - "kind": "null" - } - ] + "kind": "primitive", + "type": "string" } } ], @@ -3829,39 +3048,43 @@ } }, { - "name": "SleepResponseHeaders", - "source": "SleepResponseHeaders", + "name": "SleepStatus409ResponseHeaders", + "source": "SleepStatus409ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "ETag", - "publicName": "ETag", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "SleepStatus429ResponseHeaders", + "source": "SleepStatus429ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "X-Dedalus-Storage-Operation-Id", - "publicName": "X-Dedalus-Storage-Operation-Id", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "primitive", - "type": "string" - }, - { - "kind": "null" - } - ] + "kind": "primitive", + "type": "string" } } ], @@ -3869,39 +3092,43 @@ } }, { - "name": "SleepResponseHeaders", - "source": "SleepResponseHeaders", + "name": "SleepStatus503ResponseHeaders", + "source": "SleepStatus503ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "ETag", - "publicName": "ETag", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - }, + } + ], + "additionalProperties": false + } + }, + { + "name": "SleepStatusdefaultResponseHeaders", + "source": "SleepStatusdefaultResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "name": "X-Dedalus-Storage-Operation-Id", - "publicName": "X-Dedalus-Storage-Operation-Id", + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", "required": false, "deprecated": false, "type": { - "kind": "union", - "variants": [ - { - "kind": "primitive", - "type": "string" - }, - { - "kind": "null" - } - ] + "kind": "primitive", + "type": "string" } } ], @@ -3926,6 +3153,26 @@ "type": "string" } }, + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "Location", + "publicName": "Location", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, { "name": "X-Dedalus-Storage-Operation-Id", "publicName": "X-Dedalus-Storage-Operation-Id", @@ -3966,6 +3213,26 @@ "type": "string" } }, + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "Location", + "publicName": "Location", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, { "name": "X-Dedalus-Storage-Operation-Id", "publicName": "X-Dedalus-Storage-Operation-Id", @@ -3987,2912 +3254,506 @@ ], "additionalProperties": false } - } - ], - "resources": [ - "machines", - "machines.network", - "machines.artifacts", - "machines.ports", - "machines.ssh", - "machines.executions", - "machines.terminals", - "networks", - "usage" - ], - "publicResources": [ - "machines", - "machines.network", - "machines.artifacts", - "machines.ports", - "machines.ssh", - "machines.executions", - "machines.terminals", - "networks", - "usage" - ], - "operations": [ + }, { - "resource": "machines", - "publicResource": "machines", - "operation": "list", - "publicOperation": "list", + "name": "WakeStatus401ResponseHeaders", + "source": "WakeStatus401ResponseHeaders", + "publicAliases": [], "deprecated": false, - "method": "GET", - "path": "/v1/machines", - "pathParams": [], - "publicPathParams": [], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" - ], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "cursor", - "required": false, - "style": "form", - "explode": false - } - ], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineListParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "machine_list", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "WakeStatus403ResponseHeaders", + "source": "WakeStatus403ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "WakeStatus409ResponseHeaders", + "source": "WakeStatus409ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ], - "model": { - "name": "error_model", - "publicAliases": [] } - } - ], - "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" ], - "cursorParams": [ - "cursor" + "additionalProperties": false + } + }, + { + "name": "WakeStatus429ResponseHeaders", + "source": "WakeStatus429ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "machine_list_item", - "publicAliases": [] - } - }, - "transport": "http" + "additionalProperties": false + } }, { - "resource": "machines", - "publicResource": "machines", - "operation": "create", - "publicOperation": "create", + "name": "WakeStatus503ResponseHeaders", + "source": "WakeStatus503ResponseHeaders", + "publicAliases": [], "deprecated": false, - "method": "POST", - "path": "/v1/machines", - "pathParams": [], - "publicPathParams": [], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" - ], - "publicBodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" - ], - "bodyParamDetails": [ - { - "name": "autosleep", - "required": false - }, - { - "name": "memory_mib", - "required": false - }, - { - "name": "storage_gib", - "required": false - }, - { - "name": "vcpu", - "required": false - } - ], - "publicPositionalParams": [], - "pathParamDetails": [], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineCreateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } } ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ + "additionalProperties": false + } + }, + { + "name": "WakeStatusdefaultResponseHeaders", + "source": "WakeStatusdefaultResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } } - ] - }, - "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "CreateResponseHeaders", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "409", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines", - "publicResource": "machines", - "operation": "retrieve", - "publicOperation": "retrieve", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineRetrieveParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "machine_detail_response", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "RetrieveResponseHeaders", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines", - "publicResource": "machines", - "operation": "update", - "publicOperation": "update", - "deprecated": false, - "method": "PATCH", - "path": "/v1/machines/{machine_id}", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" - ], - "publicBodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" - ], - "bodyParamDetails": [ - { - "name": "autosleep", - "required": false - }, - { - "name": "memory_mib", - "required": false - }, - { - "name": "storage_gib", - "required": false - }, - { - "name": "vcpu", - "required": false - } - ], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineUpdateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "UpdateResponseHeaders", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "409", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines", - "publicResource": "machines", - "operation": "delete", - "publicOperation": "delete", - "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineDeleteParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "DeleteResponseHeaders", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "409", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines", - "publicResource": "machines", - "operation": "watch", - "publicOperation": "watch", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/status/stream", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id", - "Last-Event-ID" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id", - "Last-Event-ID" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - }, - { - "name": "Last-Event-ID", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineWatchParams" - }, - "response": { - "status": "200", - "contentType": "text/event-stream", - "encoding": "text", - "contents": [ - { - "contentType": "text/event-stream", - "encoding": "text" - } - ] - }, - "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - } - ], - "responseLinks": [], - "transport": "http", - "streaming": "sse" - }, - { - "resource": "machines", - "publicResource": "machines", - "operation": "sleep", - "publicOperation": "sleep", - "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/sleep", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineSleepParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "SleepResponseHeaders", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "409", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines", - "publicResource": "machines", - "operation": "wake", - "publicOperation": "wake", - "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/wake", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineWakeParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "WakeResponseHeaders", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "409", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines.network", - "publicResource": "machines.network", - "operation": "retrieve", - "publicOperation": "retrieve", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/network", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "NetworkRetrieveParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "machine_network", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines.artifacts", - "publicResource": "machines.artifacts", - "operation": "list", - "publicOperation": "list", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/artifacts", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" - ], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "cursor", - "required": false, - "style": "form", - "explode": false - } - ], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "ArtifactListParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "artifact_list", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" - ], - "cursorParams": [ - "cursor" - ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "artifact", - "publicAliases": [] - } - }, - "transport": "http" - }, - { - "resource": "machines.artifacts", - "publicResource": "machines.artifacts", - "operation": "retrieve", - "publicOperation": "retrieve", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", - "pathParams": [ - "machine_id", - "artifact_id" - ], - "publicPathParams": [ - "machine_id", - "artifact_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - }, - { - "name": "artifact_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "ArtifactRetrieveParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "artifact", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines.artifacts", - "publicResource": "machines.artifacts", - "operation": "delete", - "publicOperation": "delete", - "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", - "pathParams": [ - "machine_id", - "artifact_id" - ], - "publicPathParams": [ - "machine_id", - "artifact_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - }, - { - "name": "artifact_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "ArtifactDeleteParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "artifact", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines.ports", - "publicResource": "machines.ports", - "operation": "list", - "publicOperation": "list", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/ports", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" - ], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "cursor", - "required": false, - "style": "form", - "explode": false - } - ], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "PortListParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "port_list", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" - ], - "cursorParams": [ - "cursor" - ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "port", - "publicAliases": [] - } - }, - "transport": "http" - }, - { - "resource": "machines.ports", - "publicResource": "machines.ports", - "operation": "create", - "publicOperation": "create", - "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/ports", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [ - "port", - "protocol" - ], - "publicBodyParams": [ - "port", - "protocol" - ], - "bodyParamDetails": [ - { - "name": "port", - "required": true - }, - { - "name": "protocol", - "required": false - } - ], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "PortCreateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "port", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "409", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" - } - ], - "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "transport": "http" - }, - { - "resource": "machines.ports", - "publicResource": "machines.ports", - "operation": "retrieve", - "publicOperation": "retrieve", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/ports/{port_id}", - "pathParams": [ - "machine_id", - "port_id" - ], - "publicPathParams": [ - "machine_id", - "port_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - }, - { - "name": "port_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "PortRetrieveParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "port", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" + ], + "additionalProperties": false + } + }, + { + "name": "CreateResponseHeaders", + "source": "CreateResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ], - "model": { - "name": "error_model", - "publicAliases": [] } - } - ], - "responseLinks": [], - "transport": "http" + ], + "additionalProperties": false + } }, { - "resource": "machines.ports", - "publicResource": "machines.ports", - "operation": "delete", - "publicOperation": "delete", + "name": "CreateStatus401ResponseHeaders", + "source": "CreateStatus401ResponseHeaders", + "publicAliases": [], "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}/ports/{port_id}", - "pathParams": [ - "machine_id", - "port_id" - ], - "publicPathParams": [ - "machine_id", - "port_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - }, - { - "name": "port_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "PortDeleteParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } } - ] - }, - "responseModel": { - "name": "port", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus403ResponseHeaders", + "source": "CreateStatus403ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus409ResponseHeaders", + "source": "CreateStatus409ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus429ResponseHeaders", + "source": "CreateStatus429ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus503ResponseHeaders", + "source": "CreateStatus503ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatusdefaultResponseHeaders", + "source": "CreateStatusdefaultResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ], - "model": { - "name": "error_model", - "publicAliases": [] } - } - ], - "responseLinks": [], - "transport": "http" + ], + "additionalProperties": false + } }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "list", - "publicOperation": "list", + "name": "CreateResponseHeaders", + "source": "CreateResponseHeaders", + "publicAliases": [], "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/ssh", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" - ], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "cursor", - "required": false, - "style": "form", - "explode": false - } - ], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "SshListParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "ssh_session_list", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ], - "model": { - "name": "error_model", - "publicAliases": [] } - } - ], - "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" ], - "cursorParams": [ - "cursor" + "additionalProperties": false + } + }, + { + "name": "CreateStatus401ResponseHeaders", + "source": "CreateStatus401ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "ssh_session", - "publicAliases": [] - } - }, - "transport": "http" + "additionalProperties": false + } }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "create", - "publicOperation": "create", + "name": "CreateStatus403ResponseHeaders", + "source": "CreateStatus403ResponseHeaders", + "publicAliases": [], "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/ssh", - "pathParams": [ - "machine_id" - ], - "publicPathParams": [ - "machine_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [ - "public_key" - ], - "publicBodyParams": [ - "public_key" - ], - "bodyParamDetails": [ - { - "name": "public_key", - "required": true - } - ], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "SshCreateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } } ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ + "additionalProperties": false + } + }, + { + "name": "CreateStatus409ResponseHeaders", + "source": "CreateStatus409ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - "responseModel": { - "name": "ssh_session", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "409", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "403", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus429ResponseHeaders", + "source": "CreateStatus429ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "default", - "contentType": "application/problem+json", - "encoding": "json", - "contents": [ - { - "contentType": "application/problem+json", - "encoding": "json" + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus503ResponseHeaders", + "source": "CreateStatus503ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ], - "model": { - "name": "error_model", - "publicAliases": [] } - } - ], - "responseLinks": [], - "transport": "http" + ], + "additionalProperties": false + } }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "retrieve", - "publicOperation": "retrieve", + "name": "CreateStatusdefaultResponseHeaders", + "source": "CreateStatusdefaultResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + } + ], + "resources": [ + "machines", + "machines.ssh", + "machines.executions", + "machines.terminals" + ], + "publicResources": [ + "machines", + "machines.ssh", + "machines.executions", + "machines.terminals" + ], + "operations": [ + { + "resource": "machines", + "publicResource": "machines", + "operation": "list", + "publicOperation": "list", "deprecated": false, "method": "GET", - "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "pathParams": [ - "machine_id", - "session_id" - ], - "publicPathParams": [ - "machine_id", - "session_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" + "path": "/v1/machines", + "pathParams": [], + "publicPathParams": [], + "queryParams": [ + "limit", + "cursor" ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" + "publicQueryParams": [ + "limit", + "cursor" ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], "publicPositionalParams": [], - "pathParamDetails": [ + "pathParamDetails": [], + "queryParamDetails": [ { - "name": "machine_id", - "required": true, - "style": "simple", + "name": "limit", + "required": false, + "style": "form", "explode": false }, { - "name": "session_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", + "name": "cursor", "required": false, "style": "form", - "explode": true + "explode": false } ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "SshRetrieveParams" + "publicName": "MachineListParams" }, "response": { "status": "200", @@ -6906,7 +3767,7 @@ ] }, "responseModel": { - "name": "ssh_session", + "name": "machine_list", "publicAliases": [] }, "result": { @@ -6979,66 +3840,94 @@ "publicAliases": [] } } - ], - "responseLinks": [], + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "machine_list_item", + "publicAliases": [] + } + }, "transport": "http" }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "delete", - "publicOperation": "delete", + "resource": "machines", + "publicResource": "machines", + "operation": "create", + "publicOperation": "create", "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "pathParams": [ - "machine_id", - "session_id" - ], - "publicPathParams": [ - "machine_id", - "session_id" - ], + "method": "POST", + "path": "/v1/machines", + "pathParams": [], + "publicPathParams": [], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" + "publicBodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ + "bodyParamDetails": [ { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false + "name": "autosleep", + "required": false }, { - "name": "session_id", - "required": true, - "style": "simple", - "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ + "name": "memory_mib", + "required": false + }, { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true + "name": "storage_gib", + "required": false + }, + { + "name": "vcpu", + "required": false } ], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "SshDeleteParams" + "publicName": "MachineCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" }, "response": { "status": "200", @@ -7052,7 +3941,11 @@ ] }, "responseModel": { - "name": "ssh_session", + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "CreateResponseHeaders", "publicAliases": [] }, "result": { @@ -7060,6 +3953,7 @@ "errorStatuses": [ "401", "403", + "409", "429", "503", "default" @@ -7075,7 +3969,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus401ResponseHeaders", + "publicAliases": [] + } }, { "status": "403", @@ -7086,7 +3984,26 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "CreateStatus409ResponseHeaders", + "publicAliases": [] + } }, { "status": "429", @@ -7097,7 +4014,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus429ResponseHeaders", + "publicAliases": [] + } }, { "status": "503", @@ -7108,7 +4029,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus503ResponseHeaders", + "publicAliases": [] + } }, { "status": "default", @@ -7123,6 +4048,10 @@ "model": { "name": "error_model", "publicAliases": [] + }, + "headersModel": { + "name": "CreateStatusdefaultResponseHeaders", + "publicAliases": [] } } ], @@ -7130,33 +4059,23 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "list", - "publicOperation": "list", + "resource": "machines", + "publicResource": "machines", + "operation": "retrieve", + "publicOperation": "retrieve", "deprecated": false, "method": "GET", - "path": "/v1/machines/{machine_id}/executions", + "path": "/v1/machines/{machine_id}", "pathParams": [ "machine_id" ], "publicPathParams": [ "machine_id" ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" - ], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], @@ -7169,33 +4088,13 @@ "explode": false } ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "cursor", - "required": false, - "style": "form", - "explode": false - } - ], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "queryParamDetails": [], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionListParams" + "publicName": "MachineRetrieveParams" }, "response": { "status": "200", @@ -7209,7 +4108,11 @@ ] }, "responseModel": { - "name": "execution_list", + "name": "machine_detail_response", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "RetrieveResponseHeaders", "publicAliases": [] }, "result": { @@ -7284,34 +4187,16 @@ } ], "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" - ], - "cursorParams": [ - "cursor" - ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "execution", - "publicAliases": [] - } - }, "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "create", - "publicOperation": "create", + "resource": "machines", + "publicResource": "machines", + "operation": "update", + "publicOperation": "update", "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/executions", + "method": "PATCH", + "path": "/v1/machines/{machine_id}", "pathParams": [ "machine_id" ], @@ -7320,45 +4205,35 @@ ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [ - "command", - "cwd", - "env", - "stdin", - "timeout_ms" + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" ], "publicBodyParams": [ - "command", - "cwd", - "env", - "stdin", - "timeout_ms" + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" ], "bodyParamDetails": [ { - "name": "command", - "required": true - }, - { - "name": "cwd", + "name": "autosleep", "required": false }, { - "name": "env", + "name": "memory_mib", "required": false }, { - "name": "stdin", + "name": "storage_gib", "required": false }, { - "name": "timeout_ms", + "name": "vcpu", "required": false } ], @@ -7372,19 +4247,12 @@ } ], "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionCreateParams" + "publicName": "MachineUpdateParams" }, "requestBody": { "contentType": "application/json", @@ -7411,7 +4279,11 @@ ] }, "responseModel": { - "name": "execution", + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "UpdateResponseHeaders", "publicAliases": [] }, "result": { @@ -7435,7 +4307,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "UpdateStatus401ResponseHeaders", + "publicAliases": [] + } }, { "status": "403", @@ -7446,7 +4322,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "UpdateStatus403ResponseHeaders", + "publicAliases": [] + } }, { "status": "409", @@ -7457,7 +4337,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "UpdateStatus409ResponseHeaders", + "publicAliases": [] + } }, { "status": "429", @@ -7468,7 +4352,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "UpdateStatus429ResponseHeaders", + "publicAliases": [] + } }, { "status": "503", @@ -7479,7 +4367,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "UpdateStatus503ResponseHeaders", + "publicAliases": [] + } }, { "status": "default", @@ -7494,6 +4386,10 @@ "model": { "name": "error_model", "publicAliases": [] + }, + "headersModel": { + "name": "UpdateStatusdefaultResponseHeaders", + "publicAliases": [] } } ], @@ -7501,29 +4397,23 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "retrieve", - "publicOperation": "retrieve", + "resource": "machines", + "publicResource": "machines", + "operation": "delete", + "publicOperation": "delete", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "method": "DELETE", + "path": "/v1/machines/{machine_id}", "pathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], @@ -7534,28 +4424,15 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false } ], "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionRetrieveParams" + "publicName": "MachineDeleteParams" }, "response": { "status": "200", @@ -7569,7 +4446,11 @@ ] }, "responseModel": { - "name": "execution", + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "DeleteResponseHeaders", "publicAliases": [] }, "result": { @@ -7577,6 +4458,7 @@ "errorStatuses": [ "401", "403", + "409", "429", "503", "default" @@ -7592,7 +4474,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "DeleteStatus401ResponseHeaders", + "publicAliases": [] + } }, { "status": "403", @@ -7603,7 +4489,26 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "DeleteStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "DeleteStatus409ResponseHeaders", + "publicAliases": [] + } }, { "status": "429", @@ -7614,7 +4519,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "DeleteStatus429ResponseHeaders", + "publicAliases": [] + } }, { "status": "503", @@ -7625,7 +4534,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "DeleteStatus503ResponseHeaders", + "publicAliases": [] + } }, { "status": "default", @@ -7640,6 +4553,10 @@ "model": { "name": "error_model", "publicAliases": [] + }, + "headersModel": { + "name": "DeleteStatusdefaultResponseHeaders", + "publicAliases": [] } } ], @@ -7647,29 +4564,23 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "delete", - "publicOperation": "delete", + "resource": "machines", + "publicResource": "machines", + "operation": "sleep", + "publicOperation": "sleep", "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "method": "POST", + "path": "/v1/machines/{machine_id}/sleep", "pathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], @@ -7680,28 +4591,15 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false } ], "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionDeleteParams" + "publicName": "MachineSleepParams" }, "response": { "status": "200", @@ -7715,7 +4613,11 @@ ] }, "responseModel": { - "name": "execution", + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "SleepResponseHeaders", "publicAliases": [] }, "result": { @@ -7723,6 +4625,7 @@ "errorStatuses": [ "401", "403", + "409", "429", "503", "default" @@ -7738,7 +4641,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "SleepStatus401ResponseHeaders", + "publicAliases": [] + } }, { "status": "403", @@ -7749,7 +4656,26 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "SleepStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "SleepStatus409ResponseHeaders", + "publicAliases": [] + } }, { "status": "429", @@ -7760,7 +4686,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "SleepStatus429ResponseHeaders", + "publicAliases": [] + } }, { "status": "503", @@ -7771,7 +4701,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "SleepStatus503ResponseHeaders", + "publicAliases": [] + } }, { "status": "default", @@ -7786,6 +4720,10 @@ "model": { "name": "error_model", "publicAliases": [] + }, + "headersModel": { + "name": "SleepStatusdefaultResponseHeaders", + "publicAliases": [] } } ], @@ -7793,29 +4731,23 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "output", - "publicOperation": "output", + "resource": "machines", + "publicResource": "machines", + "operation": "wake", + "publicOperation": "wake", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", + "method": "POST", + "path": "/v1/machines/{machine_id}/wake", "pathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], @@ -7826,28 +4758,15 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false } ], "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionOutputParams" + "publicName": "MachineWakeParams" }, "response": { "status": "200", @@ -7861,7 +4780,11 @@ ] }, "responseModel": { - "name": "execution_output", + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "WakeResponseHeaders", "publicAliases": [] }, "result": { @@ -7869,6 +4792,7 @@ "errorStatuses": [ "401", "403", + "409", "429", "503", "default" @@ -7884,7 +4808,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "WakeStatus401ResponseHeaders", + "publicAliases": [] + } }, { "status": "403", @@ -7895,7 +4823,26 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "WakeStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "WakeStatus409ResponseHeaders", + "publicAliases": [] + } }, { "status": "429", @@ -7906,7 +4853,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "WakeStatus429ResponseHeaders", + "publicAliases": [] + } }, { "status": "503", @@ -7917,7 +4868,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "WakeStatus503ResponseHeaders", + "publicAliases": [] + } }, { "status": "default", @@ -7932,6 +4887,10 @@ "model": { "name": "error_model", "publicAliases": [] + }, + "headersModel": { + "name": "WakeStatusdefaultResponseHeaders", + "publicAliases": [] } } ], @@ -7939,20 +4898,18 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "events", - "publicOperation": "events", + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "list", + "publicOperation": "list", "deprecated": false, "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", + "path": "/v1/machines/{machine_id}/ssh", "pathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "queryParams": [ "limit", @@ -7962,12 +4919,8 @@ "limit", "cursor" ], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], @@ -7978,12 +4931,6 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false } ], "queryParamDetails": [ @@ -8000,19 +4947,12 @@ "explode": false } ], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionEventsParams" + "publicName": "SshListParams" }, "response": { "status": "200", @@ -8026,7 +4966,7 @@ ] }, "responseModel": { - "name": "execution_events", + "name": "ssh_session_list", "publicAliases": [] }, "result": { @@ -8115,43 +5055,42 @@ "requestLocation": "query", "responseLocation": "body", "itemModel": { - "name": "execution_event", + "name": "ssh_session", "publicAliases": [] } }, "transport": "http" }, { - "resource": "machines.terminals", - "publicResource": "machines.terminals", - "operation": "list", - "publicOperation": "list", + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "create", + "publicOperation": "create", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals", + "method": "POST", + "path": "/v1/machines/{machine_id}/ssh", "pathParams": [ "machine_id" ], "publicPathParams": [ "machine_id" ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [ + "public_key" ], - "headerParams": [ - "X-Dedalus-Org-Id" + "publicBodyParams": [ + "public_key" ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" + "bodyParamDetails": [ + { + "name": "public_key", + "required": true + } ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], "publicPositionalParams": [], "pathParamDetails": [ { @@ -8161,33 +5100,26 @@ "explode": false } ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "cursor", - "required": false, - "style": "form", - "explode": false - } - ], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "queryParamDetails": [], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "TerminalListParams" + "publicName": "SshCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" }, "response": { "status": "200", @@ -8201,7 +5133,11 @@ ] }, "responseModel": { - "name": "terminal_list", + "name": "ssh_session", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "CreateResponseHeaders", "publicAliases": [] }, "result": { @@ -8209,6 +5145,7 @@ "errorStatuses": [ "401", "403", + "409", "429", "503", "default" @@ -8224,7 +5161,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus401ResponseHeaders", + "publicAliases": [] + } }, { "status": "403", @@ -8235,7 +5176,26 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "CreateStatus409ResponseHeaders", + "publicAliases": [] + } }, { "status": "429", @@ -8246,7 +5206,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus429ResponseHeaders", + "publicAliases": [] + } }, { "status": "503", @@ -8257,7 +5221,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus503ResponseHeaders", + "publicAliases": [] + } }, { "status": "default", @@ -8272,88 +5240,39 @@ "model": { "name": "error_model", "publicAliases": [] + }, + "headersModel": { + "name": "CreateStatusdefaultResponseHeaders", + "publicAliases": [] } } ], "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" - ], - "cursorParams": [ - "cursor" - ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "terminal", - "publicAliases": [] - } - }, "transport": "http" }, { - "resource": "machines.terminals", - "publicResource": "machines.terminals", - "operation": "create", - "publicOperation": "create", + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "retrieve", + "publicOperation": "retrieve", "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/terminals", + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", "pathParams": [ - "machine_id" + "machine_id", + "session_id" ], "publicPathParams": [ - "machine_id" + "machine_id", + "session_id" ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], - "bodyParams": [ - "cwd", - "env", - "height", - "shell", - "width" - ], - "publicBodyParams": [ - "cwd", - "env", - "height", - "shell", - "width" - ], - "bodyParamDetails": [ - { - "name": "cwd", - "required": false - }, - { - "name": "env", - "required": false - }, - { - "name": "height", - "required": true - }, - { - "name": "shell", - "required": false - }, - { - "name": "width", - "required": true - } - ], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], "publicPositionalParams": [], "pathParamDetails": [ { @@ -8361,35 +5280,21 @@ "required": true, "style": "simple", "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ + }, { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true + "name": "session_id", + "required": true, + "style": "simple", + "explode": false } ], + "queryParamDetails": [], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "TerminalCreateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" + "publicName": "SshRetrieveParams" }, "response": { "status": "200", @@ -8403,7 +5308,7 @@ ] }, "responseModel": { - "name": "terminal", + "name": "ssh_session", "publicAliases": [] }, "result": { @@ -8411,7 +5316,6 @@ "errorStatuses": [ "401", "403", - "409", "429", "503", "default" @@ -8440,17 +5344,6 @@ } ] }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "429", "contentType": "application/json", @@ -8493,29 +5386,25 @@ "transport": "http" }, { - "resource": "machines.terminals", - "publicResource": "machines.terminals", - "operation": "retrieve", - "publicOperation": "retrieve", + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "delete", + "publicOperation": "delete", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", "pathParams": [ "machine_id", - "terminal_id" + "session_id" ], "publicPathParams": [ "machine_id", - "terminal_id" + "session_id" ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], @@ -8528,26 +5417,19 @@ "explode": false }, { - "name": "terminal_id", + "name": "session_id", "required": true, "style": "simple", "explode": false } ], "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "TerminalRetrieveParams" + "publicName": "SshDeleteParams" }, "response": { "status": "200", @@ -8561,7 +5443,7 @@ ] }, "responseModel": { - "name": "terminal", + "name": "ssh_session", "publicAliases": [] }, "result": { @@ -8639,29 +5521,29 @@ "transport": "http" }, { - "resource": "machines.terminals", - "publicResource": "machines.terminals", - "operation": "delete", - "publicOperation": "delete", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "list", + "publicOperation": "list", "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions", "pathParams": [ - "machine_id", - "terminal_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "terminal_id" + "machine_id" ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" + "queryParams": [ + "limit", + "cursor" ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" + "publicQueryParams": [ + "limit", + "cursor" ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], @@ -8672,28 +5554,28 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "terminal_id", - "required": true, - "style": "simple", - "explode": false } ], - "queryParamDetails": [], - "headerParamDetails": [ + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, { - "name": "X-Dedalus-Org-Id", + "name": "cursor", "required": false, "style": "form", - "explode": true + "explode": false } ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "TerminalDeleteParams" + "publicName": "ExecutionListParams" }, "response": { "status": "200", @@ -8707,7 +5589,7 @@ ] }, "responseModel": { - "name": "terminal", + "name": "execution_list", "publicAliases": [] }, "result": { @@ -8782,35 +5664,80 @@ } ], "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "execution", + "publicAliases": [] + } + }, "transport": "http" }, { - "resource": "machines.terminals", - "publicResource": "machines.terminals", - "operation": "connect", - "publicOperation": "connect", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "create", + "publicOperation": "create", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", + "method": "POST", + "path": "/v1/machines/{machine_id}/executions", "pathParams": [ - "machine_id", - "terminal_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "terminal_id" + "machine_id" ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [ + "command", + "cwd", + "env", + "stdin", + "timeout_ms" ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" + "publicBodyParams": [ + "command", + "cwd", + "env", + "stdin", + "timeout_ms" + ], + "bodyParamDetails": [ + { + "name": "command", + "required": true + }, + { + "name": "cwd", + "required": false + }, + { + "name": "env", + "required": false + }, + { + "name": "stdin", + "required": false + }, + { + "name": "timeout_ms", + "required": false + } ], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], "publicPositionalParams": [], "pathParamDetails": [ { @@ -8818,37 +5745,57 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "terminal_id", - "required": true, - "style": "simple", - "explode": false } ], "queryParamDetails": [], - "headerParamDetails": [ - { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true - } - ], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "TerminalConnectParams" + "publicName": "ExecutionCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "execution", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "CreateResponseHeaders", + "publicAliases": [] }, "result": { - "successStatus": "101", + "successStatus": "200", "errorStatuses": [ "401", "403", "409", "429", - "503" + "503", + "default" ] }, "errorResponses": [ @@ -8861,7 +5808,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus401ResponseHeaders", + "publicAliases": [] + } }, { "status": "403", @@ -8872,7 +5823,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus403ResponseHeaders", + "publicAliases": [] + } }, { "status": "409", @@ -8883,7 +5838,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus409ResponseHeaders", + "publicAliases": [] + } }, { "status": "429", @@ -8894,7 +5853,11 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus429ResponseHeaders", + "publicAliases": [] + } }, { "status": "503", @@ -8905,71 +5868,80 @@ "contentType": "application/json", "encoding": "json" } - ] + ], + "headersModel": { + "name": "CreateStatus503ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + }, + "headersModel": { + "name": "CreateStatusdefaultResponseHeaders", + "publicAliases": [] + } } ], "responseLinks": [], - "transport": "websocket", - "websocket": { - "sendModel": { - "name": "terminal_client_event", - "publicAliases": [] - }, - "receiveModel": { - "name": "terminal_server_event", - "publicAliases": [] - }, - "eventNameSeparator": "." - } + "transport": "http" }, { - "resource": "networks", - "publicResource": "networks", + "resource": "machines.executions", + "publicResource": "machines.executions", "operation": "retrieve", "publicOperation": "retrieve", "deprecated": false, "method": "GET", - "path": "/v1/networks/{network_id}", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", "pathParams": [ - "network_id" + "machine_id", + "execution_id" ], "publicPathParams": [ - "network_id" + "machine_id", + "execution_id" ], "queryParams": [], "publicQueryParams": [], - "headerParams": [ - "X-Dedalus-Org-Id" - ], - "publicHeaderParams": [ - "X-Dedalus-Org-Id" - ], + "headerParams": [], + "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], "publicPositionalParams": [], "pathParamDetails": [ { - "name": "network_id", + "name": "machine_id", "required": true, "style": "simple", "explode": false - } - ], - "queryParamDetails": [], - "headerParamDetails": [ + }, { - "name": "X-Dedalus-Org-Id", - "required": false, - "style": "form", - "explode": true + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false } ], + "queryParamDetails": [], + "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "NetworkRetrieveParams" + "publicName": "ExecutionRetrieveParams" }, "response": { "status": "200", @@ -8983,7 +5955,7 @@ ] }, "responseModel": { - "name": "network", + "name": "execution", "publicAliases": [] }, "result": { @@ -8991,6 +5963,8 @@ "errorStatuses": [ "401", "403", + "429", + "503", "default" ] }, @@ -9017,6 +5991,28 @@ } ] }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, { "status": "default", "contentType": "application/problem+json", @@ -9037,42 +6033,50 @@ "transport": "http" }, { - "resource": "usage", - "publicResource": "usage", - "operation": "retrieve", - "publicOperation": "retrieve", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "delete", + "publicOperation": "delete", "deprecated": false, - "method": "GET", - "path": "/v1/usage", - "pathParams": [], - "publicPathParams": [], - "queryParams": [ - "period_start" + "method": "DELETE", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "pathParams": [ + "machine_id", + "execution_id" ], - "publicQueryParams": [ - "period_start" + "publicPathParams": [ + "machine_id", + "execution_id" ], + "queryParams": [], + "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], "publicPositionalParams": [], - "pathParamDetails": [], - "queryParamDetails": [ + "pathParamDetails": [ { - "name": "period_start", - "required": false, - "style": "form", + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", "explode": false } ], + "queryParamDetails": [], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "UsageRetrieveParams" + "publicName": "ExecutionDeleteParams" }, "response": { "status": "200", @@ -9086,32 +6090,20 @@ ] }, "responseModel": { - "name": "org_usage", + "name": "execution", "publicAliases": [] }, "result": { "successStatus": "200", "errorStatuses": [ - "400", "401", "403", - "500", - "502", + "429", + "503", "default" ] }, "errorResponses": [ - { - "status": "400", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "401", "contentType": "application/json", @@ -9135,7 +6127,7 @@ ] }, { - "status": "500", + "status": "429", "contentType": "application/json", "encoding": "json", "contents": [ @@ -9146,7 +6138,7 @@ ] }, { - "status": "502", + "status": "503", "contentType": "application/json", "encoding": "json", "contents": [ @@ -9176,66 +6168,50 @@ "transport": "http" }, { - "resource": "usage", - "publicResource": "usage", - "operation": "machineCompute", - "publicOperation": "machineCompute", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "output", + "publicOperation": "output", "deprecated": false, "method": "GET", - "path": "/v1/usage/machines/compute", - "pathParams": [], - "publicPathParams": [], - "queryParams": [ - "period_start", - "period_end", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", + "pathParams": [ "machine_id", - "granularity" + "execution_id" ], - "publicQueryParams": [ - "period_start", - "period_end", + "publicPathParams": [ "machine_id", - "granularity" + "execution_id" ], + "queryParams": [], + "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], "bodyParams": [], "publicBodyParams": [], "bodyParamDetails": [], "publicPositionalParams": [], - "pathParamDetails": [], - "queryParamDetails": [ - { - "name": "period_start", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "period_end", - "required": false, - "style": "form", - "explode": false - }, + "pathParamDetails": [ { "name": "machine_id", - "required": false, - "style": "form", + "required": true, + "style": "simple", "explode": false }, { - "name": "granularity", - "required": false, - "style": "form", + "name": "execution_id", + "required": true, + "style": "simple", "explode": false } ], + "queryParamDetails": [], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "UsageMachineComputeParams" + "publicName": "ExecutionOutputParams" }, "response": { "status": "200", @@ -9249,32 +6225,20 @@ ] }, "responseModel": { - "name": "machine_compute_usage", + "name": "execution_output", "publicAliases": [] }, "result": { "successStatus": "200", "errorStatuses": [ - "400", "401", "403", - "500", - "502", + "429", + "503", "default" ] }, "errorResponses": [ - { - "status": "400", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "401", "contentType": "application/json", @@ -9298,7 +6262,7 @@ ] }, { - "status": "500", + "status": "429", "contentType": "application/json", "encoding": "json", "contents": [ @@ -9309,7 +6273,7 @@ ] }, { - "status": "502", + "status": "503", "contentType": "application/json", "encoding": "json", "contents": [ @@ -9339,24 +6303,28 @@ "transport": "http" }, { - "resource": "usage", - "publicResource": "usage", - "operation": "machineStorage", - "publicOperation": "machineStorage", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "events", + "publicOperation": "events", "deprecated": false, "method": "GET", - "path": "/v1/usage/machines/storage", - "pathParams": [], - "publicPathParams": [], + "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", + "pathParams": [ + "machine_id", + "execution_id" + ], + "publicPathParams": [ + "machine_id", + "execution_id" + ], "queryParams": [ - "period_start", - "period_end", - "machine_id" + "limit", + "cursor" ], "publicQueryParams": [ - "period_start", - "period_end", - "machine_id" + "limit", + "cursor" ], "headerParams": [], "publicHeaderParams": [], @@ -9364,22 +6332,29 @@ "publicBodyParams": [], "bodyParamDetails": [], "publicPositionalParams": [], - "pathParamDetails": [], - "queryParamDetails": [ + "pathParamDetails": [ { - "name": "period_start", - "required": false, - "style": "form", + "name": "machine_id", + "required": true, + "style": "simple", "explode": false }, { - "name": "period_end", + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", "required": false, "style": "form", "explode": false }, { - "name": "machine_id", + "name": "cursor", "required": false, "style": "form", "explode": false @@ -9390,7 +6365,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "UsageMachineStorageParams" + "publicName": "ExecutionEventsParams" }, "response": { "status": "200", @@ -9404,32 +6379,20 @@ ] }, "responseModel": { - "name": "machine_storage_usage", + "name": "execution_events", "publicAliases": [] }, "result": { "successStatus": "200", "errorStatuses": [ - "400", "401", "403", - "500", - "502", + "429", + "503", "default" ] }, "errorResponses": [ - { - "status": "400", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "401", "contentType": "application/json", @@ -9453,7 +6416,7 @@ ] }, { - "status": "500", + "status": "429", "contentType": "application/json", "encoding": "json", "contents": [ @@ -9464,7 +6427,7 @@ ] }, { - "status": "502", + "status": "503", "contentType": "application/json", "encoding": "json", "contents": [ @@ -9491,7 +6454,74 @@ } ], "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "execution_event", + "publicAliases": [] + } + }, "transport": "http" + }, + { + "resource": "machines.terminals", + "publicResource": "machines.terminals", + "operation": "connect", + "publicOperation": "connect", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", + "pathParams": [ + "machine_id", + "terminal_id" + ], + "publicPathParams": [ + "machine_id", + "terminal_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true + }, + { + "name": "terminal_id", + "required": true + } + ], + "queryParamDetails": [], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "TerminalConnectParams" + }, + "errorResponses": [], + "responseLinks": [], + "transport": "websocket", + "websocket": { + "eventNameSeparator": "." + } } ], "webhooks": [] diff --git a/src/dedalus_sdk/_client.py b/src/dedalus_sdk/_client.py index 0ba30fe..5cf4d36 100644 --- a/src/dedalus_sdk/_client.py +++ b/src/dedalus_sdk/_client.py @@ -33,10 +33,8 @@ from ._version import __version__ if TYPE_CHECKING: - from .resources import machines, networks, usage + from .resources import machines from .resources.machines import MachinesResource, AsyncMachinesResource - from .resources.networks import NetworksResource, AsyncNetworksResource - from .resources.usage import UsageResource, AsyncUsageResource # Serializes lazy resource imports so concurrent cold access from multiple # threads cannot deadlock on CPython import locks (see CPython 3.14). @@ -164,18 +162,6 @@ def machines(self) -> "MachinesResource": from .resources.machines import MachinesResource return MachinesResource(self) - @cached_property - def networks(self) -> "NetworksResource": - with _RESOURCE_IMPORT_LOCK: - from .resources.networks import NetworksResource - return NetworksResource(self) - - @cached_property - def usage(self) -> "UsageResource": - with _RESOURCE_IMPORT_LOCK: - from .resources.usage import UsageResource - return UsageResource(self) - @cached_property def with_raw_response(self) -> DedalusWithRawResponse: return DedalusWithRawResponse(self) @@ -463,18 +449,6 @@ def machines(self) -> "AsyncMachinesResource": from .resources.machines import AsyncMachinesResource return AsyncMachinesResource(self) - @cached_property - def networks(self) -> "AsyncNetworksResource": - with _RESOURCE_IMPORT_LOCK: - from .resources.networks import AsyncNetworksResource - return AsyncNetworksResource(self) - - @cached_property - def usage(self) -> "AsyncUsageResource": - with _RESOURCE_IMPORT_LOCK: - from .resources.usage import AsyncUsageResource - return AsyncUsageResource(self) - @cached_property def with_raw_response(self) -> AsyncDedalusWithRawResponse: return AsyncDedalusWithRawResponse(self) @@ -655,18 +629,6 @@ def machines(self) -> machines.MachinesResourceWithRawResponse: from .resources.machines import MachinesResourceWithRawResponse return MachinesResourceWithRawResponse(self._client.machines) - @cached_property - def networks(self) -> networks.NetworksResourceWithRawResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.networks import NetworksResourceWithRawResponse - return NetworksResourceWithRawResponse(self._client.networks) - - @cached_property - def usage(self) -> usage.UsageResourceWithRawResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.usage import UsageResourceWithRawResponse - return UsageResourceWithRawResponse(self._client.usage) - class AsyncDedalusWithRawResponse: _client: AsyncDedalus @@ -680,18 +642,6 @@ def machines(self) -> machines.AsyncMachinesResourceWithRawResponse: from .resources.machines import AsyncMachinesResourceWithRawResponse return AsyncMachinesResourceWithRawResponse(self._client.machines) - @cached_property - def networks(self) -> networks.AsyncNetworksResourceWithRawResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.networks import AsyncNetworksResourceWithRawResponse - return AsyncNetworksResourceWithRawResponse(self._client.networks) - - @cached_property - def usage(self) -> usage.AsyncUsageResourceWithRawResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.usage import AsyncUsageResourceWithRawResponse - return AsyncUsageResourceWithRawResponse(self._client.usage) - class DedalusWithStreamedResponse: _client: Dedalus @@ -705,18 +655,6 @@ def machines(self) -> machines.MachinesResourceWithStreamingResponse: from .resources.machines import MachinesResourceWithStreamingResponse return MachinesResourceWithStreamingResponse(self._client.machines) - @cached_property - def networks(self) -> networks.NetworksResourceWithStreamingResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.networks import NetworksResourceWithStreamingResponse - return NetworksResourceWithStreamingResponse(self._client.networks) - - @cached_property - def usage(self) -> usage.UsageResourceWithStreamingResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.usage import UsageResourceWithStreamingResponse - return UsageResourceWithStreamingResponse(self._client.usage) - class AsyncDedalusWithStreamedResponse: _client: AsyncDedalus @@ -730,18 +668,6 @@ def machines(self) -> machines.AsyncMachinesResourceWithStreamingResponse: from .resources.machines import AsyncMachinesResourceWithStreamingResponse return AsyncMachinesResourceWithStreamingResponse(self._client.machines) - @cached_property - def networks(self) -> networks.AsyncNetworksResourceWithStreamingResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.networks import AsyncNetworksResourceWithStreamingResponse - return AsyncNetworksResourceWithStreamingResponse(self._client.networks) - - @cached_property - def usage(self) -> usage.AsyncUsageResourceWithStreamingResponse: - with _RESOURCE_IMPORT_LOCK: - from .resources.usage import AsyncUsageResourceWithStreamingResponse - return AsyncUsageResourceWithStreamingResponse(self._client.usage) - # Alias names for the documented `Client` / `AsyncClient` symbols. Client = Dedalus diff --git a/src/dedalus_sdk/_streaming.py b/src/dedalus_sdk/_streaming.py index e759a64..172e796 100644 --- a/src/dedalus_sdk/_streaming.py +++ b/src/dedalus_sdk/_streaming.py @@ -59,23 +59,13 @@ def __stream__(self) -> Iterator[_T]: try: for sse in iterator: - if sse.event == "error": - body = sse.data - - try: - body = sse.json() - err_msg = f"{body}" - except Exception: - err_msg = sse.data or f"Error code: {response.status_code}" - - raise self._client._make_status_error( - err_msg, - body=body, - response=self.response, - ) - - if True: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) + if not sse.data: + continue + try: + payload = sse.json() + except Exception: + payload = sse.data + yield process_data(data=payload, cast_to=cast_to, response=response) finally: # Ensure the response is closed even if the consumer doesn't read all data response.close() @@ -141,23 +131,13 @@ async def __stream__(self) -> AsyncIterator[_T]: try: async for sse in iterator: - if sse.event == "error": - body = sse.data - - try: - body = sse.json() - err_msg = f"{body}" - except Exception: - err_msg = sse.data or f"Error code: {response.status_code}" - - raise self._client._make_status_error( - err_msg, - body=body, - response=self.response, - ) - - if True: - yield process_data(data=sse.json(), cast_to=cast_to, response=response) + if not sse.data: + continue + try: + payload = sse.json() + except Exception: + payload = sse.data + yield process_data(data=payload, cast_to=cast_to, response=response) finally: # Ensure the response is closed even if the consumer doesn't read all data await response.aclose() diff --git a/src/dedalus_sdk/resources/__init__.py b/src/dedalus_sdk/resources/__init__.py index f20d857..a514d0c 100644 --- a/src/dedalus_sdk/resources/__init__.py +++ b/src/dedalus_sdk/resources/__init__.py @@ -8,22 +8,6 @@ MachinesResourceWithStreamingResponse, AsyncMachinesResourceWithStreamingResponse, ) -from .networks import ( - NetworksResource, - AsyncNetworksResource, - NetworksResourceWithRawResponse, - AsyncNetworksResourceWithRawResponse, - NetworksResourceWithStreamingResponse, - AsyncNetworksResourceWithStreamingResponse, -) -from .usage import ( - UsageResource, - AsyncUsageResource, - UsageResourceWithRawResponse, - AsyncUsageResourceWithRawResponse, - UsageResourceWithStreamingResponse, - AsyncUsageResourceWithStreamingResponse, -) __all__ = [ "MachinesResource", @@ -32,16 +16,4 @@ "AsyncMachinesResourceWithRawResponse", "MachinesResourceWithStreamingResponse", "AsyncMachinesResourceWithStreamingResponse", - "NetworksResource", - "AsyncNetworksResource", - "NetworksResourceWithRawResponse", - "AsyncNetworksResourceWithRawResponse", - "NetworksResourceWithStreamingResponse", - "AsyncNetworksResourceWithStreamingResponse", - "UsageResource", - "AsyncUsageResource", - "UsageResourceWithRawResponse", - "AsyncUsageResourceWithRawResponse", - "UsageResourceWithStreamingResponse", - "AsyncUsageResourceWithStreamingResponse", ] diff --git a/src/dedalus_sdk/resources/machines/__init__.py b/src/dedalus_sdk/resources/machines/__init__.py index da88c79..24b07c4 100644 --- a/src/dedalus_sdk/resources/machines/__init__.py +++ b/src/dedalus_sdk/resources/machines/__init__.py @@ -8,30 +8,6 @@ MachinesResourceWithStreamingResponse, AsyncMachinesResourceWithStreamingResponse, ) -from .network import ( - NetworkResource, - AsyncNetworkResource, - NetworkResourceWithRawResponse, - AsyncNetworkResourceWithRawResponse, - NetworkResourceWithStreamingResponse, - AsyncNetworkResourceWithStreamingResponse, -) -from .artifacts import ( - ArtifactsResource, - AsyncArtifactsResource, - ArtifactsResourceWithRawResponse, - AsyncArtifactsResourceWithRawResponse, - ArtifactsResourceWithStreamingResponse, - AsyncArtifactsResourceWithStreamingResponse, -) -from .ports import ( - PortsResource, - AsyncPortsResource, - PortsResourceWithRawResponse, - AsyncPortsResourceWithRawResponse, - PortsResourceWithStreamingResponse, - AsyncPortsResourceWithStreamingResponse, -) from .ssh import ( SSHResource, AsyncSSHResource, @@ -64,24 +40,6 @@ "AsyncMachinesResourceWithRawResponse", "MachinesResourceWithStreamingResponse", "AsyncMachinesResourceWithStreamingResponse", - "NetworkResource", - "AsyncNetworkResource", - "NetworkResourceWithRawResponse", - "AsyncNetworkResourceWithRawResponse", - "NetworkResourceWithStreamingResponse", - "AsyncNetworkResourceWithStreamingResponse", - "ArtifactsResource", - "AsyncArtifactsResource", - "ArtifactsResourceWithRawResponse", - "AsyncArtifactsResourceWithRawResponse", - "ArtifactsResourceWithStreamingResponse", - "AsyncArtifactsResourceWithStreamingResponse", - "PortsResource", - "AsyncPortsResource", - "PortsResourceWithRawResponse", - "AsyncPortsResourceWithRawResponse", - "PortsResourceWithStreamingResponse", - "AsyncPortsResourceWithStreamingResponse", "SSHResource", "AsyncSSHResource", "SSHResourceWithRawResponse", diff --git a/src/dedalus_sdk/resources/machines/artifacts.py b/src/dedalus_sdk/resources/machines/artifacts.py deleted file mode 100644 index c499710..0000000 --- a/src/dedalus_sdk/resources/machines/artifacts.py +++ /dev/null @@ -1,432 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.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, strip_not_given -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...pagination import SyncCursorPage, AsyncCursorPage -from ..._base_client import AsyncPaginator, make_request_options -from ...types.machines import artifact_list_params -from ...types.machines.artifact import Artifact - -__all__ = ["ArtifactsResource", "AsyncArtifactsResource"] - - -class ArtifactsResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> ArtifactsResourceWithRawResponse: - return ArtifactsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> ArtifactsResourceWithStreamingResponse: - return ArtifactsResourceWithStreamingResponse(self) - - def list( - self, - *, - machine_id: str, - limit: int | Omit = omit, - cursor: str | Omit = omit, - x_dedalus_org_id: 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, - ) -> SyncCursorPage[Artifact]: - """ - List artifacts - - Args: - machine_id: Path parameter. - limit: Query parameter. - cursor: Query parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - SyncCursorPage[Artifact]: OK - - Example: - ```python - page = client.machines.artifacts.list( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get_api_list( - path_template("/v1/machines/{machine_id}/artifacts", **{"machine_id": machine_id}), - page=SyncCursorPage[Artifact], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"limit": limit, "cursor": cursor}, artifact_list_params.ArtifactListParams), - ), - model=Artifact, - method="get", - ) - - def retrieve( - self, - *, - machine_id: str, - artifact_id: str, - x_dedalus_org_id: 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, - ) -> Artifact: - """ - Get artifact - - Args: - machine_id: Path parameter. - artifact_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Artifact: OK - - Example: - ```python - artifact = client.machines.artifacts.retrieve( - machine_id="machineID", - artifact_id="artifactID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): - raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get( - path_template( - "/v1/machines/{machine_id}/artifacts/{artifact_id}", - **{"machine_id": machine_id, "artifact_id": artifact_id}, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Artifact, - ) - - def delete( - self, - *, - machine_id: str, - artifact_id: str, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Artifact: - """ - Delete artifact - - Args: - machine_id: Path parameter. - artifact_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Artifact: OK - - Example: - ```python - artifact = client.machines.artifacts.delete( - machine_id="machineID", - artifact_id="artifactID", - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): - raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._delete( - path_template( - "/v1/machines/{machine_id}/artifacts/{artifact_id}", - **{"machine_id": machine_id, "artifact_id": artifact_id}, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Artifact, - ) - - -class AsyncArtifactsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncArtifactsResourceWithRawResponse: - return AsyncArtifactsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncArtifactsResourceWithStreamingResponse: - return AsyncArtifactsResourceWithStreamingResponse(self) - - def list( - self, - *, - machine_id: str, - limit: int | Omit = omit, - cursor: str | Omit = omit, - x_dedalus_org_id: 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, - ) -> AsyncPaginator[Artifact, AsyncCursorPage[Artifact]]: - """ - List artifacts - - Args: - machine_id: Path parameter. - limit: Query parameter. - cursor: Query parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - AsyncPaginator[Artifact, AsyncCursorPage[Artifact]]: OK - - Example: - ```python - page = client.machines.artifacts.list( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get_api_list( - path_template("/v1/machines/{machine_id}/artifacts", **{"machine_id": machine_id}), - page=AsyncCursorPage[Artifact], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"limit": limit, "cursor": cursor}, artifact_list_params.ArtifactListParams), - ), - model=Artifact, - method="get", - ) - - async def retrieve( - self, - *, - machine_id: str, - artifact_id: str, - x_dedalus_org_id: 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, - ) -> Artifact: - """ - Get artifact - - Args: - machine_id: Path parameter. - artifact_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Artifact: OK - - Example: - ```python - artifact = await client.machines.artifacts.retrieve( - machine_id="machineID", - artifact_id="artifactID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): - raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._get( - path_template( - "/v1/machines/{machine_id}/artifacts/{artifact_id}", - **{"machine_id": machine_id, "artifact_id": artifact_id}, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Artifact, - ) - - async def delete( - self, - *, - machine_id: str, - artifact_id: str, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Artifact: - """ - Delete artifact - - Args: - machine_id: Path parameter. - artifact_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Artifact: OK - - Example: - ```python - artifact = await client.machines.artifacts.delete( - machine_id="machineID", - artifact_id="artifactID", - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if artifact_id is None or (isinstance(artifact_id, str) and not artifact_id): - raise ValueError(f"Expected a non-empty value for `artifact_id` but received {artifact_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._delete( - path_template( - "/v1/machines/{machine_id}/artifacts/{artifact_id}", - **{"machine_id": machine_id, "artifact_id": artifact_id}, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Artifact, - ) - - -class ArtifactsResourceWithRawResponse: - def __init__(self, artifacts: ArtifactsResource) -> None: - self._artifacts = artifacts - - self.list = to_raw_response_wrapper( - artifacts.list, - ) - self.retrieve = to_raw_response_wrapper( - artifacts.retrieve, - ) - self.delete = to_raw_response_wrapper( - artifacts.delete, - ) - - -class AsyncArtifactsResourceWithRawResponse: - def __init__(self, artifacts: AsyncArtifactsResource) -> None: - self._artifacts = artifacts - - self.list = async_to_raw_response_wrapper( - artifacts.list, - ) - self.retrieve = async_to_raw_response_wrapper( - artifacts.retrieve, - ) - self.delete = async_to_raw_response_wrapper( - artifacts.delete, - ) - - -class ArtifactsResourceWithStreamingResponse: - def __init__(self, artifacts: ArtifactsResource) -> None: - self._artifacts = artifacts - - self.list = to_streamed_response_wrapper( - artifacts.list, - ) - self.retrieve = to_streamed_response_wrapper( - artifacts.retrieve, - ) - self.delete = to_streamed_response_wrapper( - artifacts.delete, - ) - - -class AsyncArtifactsResourceWithStreamingResponse: - def __init__(self, artifacts: AsyncArtifactsResource) -> None: - self._artifacts = artifacts - - self.list = async_to_streamed_response_wrapper( - artifacts.list, - ) - self.retrieve = async_to_streamed_response_wrapper( - artifacts.retrieve, - ) - self.delete = async_to_streamed_response_wrapper( - artifacts.delete, - ) diff --git a/src/dedalus_sdk/resources/machines/executions.py b/src/dedalus_sdk/resources/machines/executions.py index 36d1b8b..4677392 100644 --- a/src/dedalus_sdk/resources/machines/executions.py +++ b/src/dedalus_sdk/resources/machines/executions.py @@ -8,7 +8,7 @@ from ..._types import SequenceNotStr from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform, strip_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 ( @@ -42,7 +42,6 @@ def list( machine_id: str, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -54,10 +53,9 @@ def list( List executions Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -69,13 +67,12 @@ def list( Example: ```python page = client.machines.executions.list( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), page=SyncCursorPage[Execution], @@ -99,7 +96,6 @@ def create( env: Dict[str, str] | Omit = omit, stdin: str | Omit = omit, timeout_ms: int | Omit = omit, - x_dedalus_org_id: 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, @@ -112,13 +108,12 @@ def create( Create execution Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. command: Body parameter. cwd: Body parameter. env: Body parameter. stdin: Body parameter. timeout_ms: Body parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -131,7 +126,7 @@ def create( Example: ```python execution = client.machines.executions.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", command=[""], idempotency_key="", ) @@ -139,7 +134,6 @@ def create( """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), body=maybe_transform( @@ -167,7 +161,6 @@ def retrieve( *, machine_id: str, execution_id: str, - x_dedalus_org_id: 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, @@ -179,9 +172,8 @@ def retrieve( Get execution Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -193,7 +185,7 @@ def retrieve( Example: ```python execution = client.machines.executions.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -202,7 +194,6 @@ def retrieve( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get( path_template( "/v1/machines/{machine_id}/executions/{execution_id}", @@ -219,7 +210,6 @@ def delete( *, machine_id: str, execution_id: str, - x_dedalus_org_id: 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, @@ -232,9 +222,8 @@ def delete( Delete execution Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -247,7 +236,7 @@ def delete( Example: ```python execution = client.machines.executions.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", idempotency_key="", ) @@ -257,7 +246,6 @@ def delete( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._delete( path_template( "/v1/machines/{machine_id}/executions/{execution_id}", @@ -278,7 +266,6 @@ def output( *, machine_id: str, execution_id: str, - x_dedalus_org_id: 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, @@ -290,9 +277,8 @@ def output( Get execution output Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -304,7 +290,7 @@ def output( Example: ```python execution = client.machines.executions.output( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -313,7 +299,6 @@ def output( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get( path_template( "/v1/machines/{machine_id}/executions/{execution_id}/output", @@ -332,7 +317,6 @@ def events( execution_id: str, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -344,11 +328,10 @@ def events( List execution events Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -360,7 +343,7 @@ def events( Example: ```python page = client.machines.executions.events( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -369,7 +352,6 @@ def events( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template( "/v1/machines/{machine_id}/executions/{execution_id}/events", @@ -405,7 +387,6 @@ def list( machine_id: str, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -417,10 +398,9 @@ def list( List executions Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -432,13 +412,12 @@ def list( Example: ```python page = client.machines.executions.list( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), page=AsyncCursorPage[Execution], @@ -462,7 +441,6 @@ async def create( env: Dict[str, str] | Omit = omit, stdin: str | Omit = omit, timeout_ms: int | Omit = omit, - x_dedalus_org_id: 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, @@ -475,13 +453,12 @@ async def create( Create execution Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. command: Body parameter. cwd: Body parameter. env: Body parameter. stdin: Body parameter. timeout_ms: Body parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -494,7 +471,7 @@ async def create( Example: ```python execution = await client.machines.executions.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", command=[""], idempotency_key="", ) @@ -502,7 +479,6 @@ async def create( """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( path_template("/v1/machines/{machine_id}/executions", **{"machine_id": machine_id}), body=await async_maybe_transform( @@ -530,7 +506,6 @@ async def retrieve( *, machine_id: str, execution_id: str, - x_dedalus_org_id: 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, @@ -542,9 +517,8 @@ async def retrieve( Get execution Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -556,7 +530,7 @@ async def retrieve( Example: ```python execution = await client.machines.executions.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -565,7 +539,6 @@ async def retrieve( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._get( path_template( "/v1/machines/{machine_id}/executions/{execution_id}", @@ -582,7 +555,6 @@ async def delete( *, machine_id: str, execution_id: str, - x_dedalus_org_id: 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, @@ -595,9 +567,8 @@ async def delete( Delete execution Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -610,7 +581,7 @@ async def delete( Example: ```python execution = await client.machines.executions.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", idempotency_key="", ) @@ -620,7 +591,6 @@ async def delete( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._delete( path_template( "/v1/machines/{machine_id}/executions/{execution_id}", @@ -641,7 +611,6 @@ async def output( *, machine_id: str, execution_id: str, - x_dedalus_org_id: 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, @@ -653,9 +622,8 @@ async def output( Get execution output Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -667,7 +635,7 @@ async def output( Example: ```python execution = await client.machines.executions.output( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -676,7 +644,6 @@ async def output( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._get( path_template( "/v1/machines/{machine_id}/executions/{execution_id}/output", @@ -695,7 +662,6 @@ def events( execution_id: str, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -707,11 +673,10 @@ def events( List execution events Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. execution_id: Path parameter. limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -723,7 +688,7 @@ def events( Example: ```python page = client.machines.executions.events( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) ``` @@ -732,7 +697,6 @@ def events( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if execution_id is None or (isinstance(execution_id, str) and not execution_id): raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template( "/v1/machines/{machine_id}/executions/{execution_id}/events", diff --git a/src/dedalus_sdk/resources/machines/machines.py b/src/dedalus_sdk/resources/machines/machines.py index 396bb1d..cf60917 100644 --- a/src/dedalus_sdk/resources/machines/machines.py +++ b/src/dedalus_sdk/resources/machines/machines.py @@ -5,7 +5,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform, strip_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 ( @@ -16,31 +16,6 @@ ) from ...pagination import SyncCursorPage, AsyncCursorPage from ..._base_client import AsyncPaginator, make_request_options -from ..._streaming import Stream, AsyncStream -from .network import ( - NetworkResource, - AsyncNetworkResource, - NetworkResourceWithRawResponse, - AsyncNetworkResourceWithRawResponse, - NetworkResourceWithStreamingResponse, - AsyncNetworkResourceWithStreamingResponse, -) -from .artifacts import ( - ArtifactsResource, - AsyncArtifactsResource, - ArtifactsResourceWithRawResponse, - AsyncArtifactsResourceWithRawResponse, - ArtifactsResourceWithStreamingResponse, - AsyncArtifactsResourceWithStreamingResponse, -) -from .ports import ( - PortsResource, - AsyncPortsResource, - PortsResourceWithRawResponse, - AsyncPortsResourceWithRawResponse, - PortsResourceWithStreamingResponse, - AsyncPortsResourceWithStreamingResponse, -) from .ssh import ( SSHResource, AsyncSSHResource, @@ -74,18 +49,6 @@ class MachinesResource(SyncAPIResource): - @cached_property - def network(self) -> NetworkResource: - return NetworkResource(self._client) - - @cached_property - def artifacts(self) -> ArtifactsResource: - return ArtifactsResource(self._client) - - @cached_property - def ports(self) -> PortsResource: - return PortsResource(self._client) - @cached_property def ssh(self) -> SSHResource: return SSHResource(self._client) @@ -111,7 +74,6 @@ def list( *, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -125,7 +87,6 @@ def list( Args: limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -139,7 +100,6 @@ def list( page = client.machines.list() ``` """ - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( "/v1/machines", page=SyncCursorPage[MachineListItem], @@ -161,7 +121,6 @@ def create( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, - x_dedalus_org_id: 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, @@ -178,7 +137,6 @@ def create( memory_mib: Memory in MiB. storage_gib: Storage in GiB. vcpu: CPU in vCPUs. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -199,7 +157,6 @@ def create( ) ``` """ - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( "/v1/machines", body=maybe_transform( @@ -225,7 +182,6 @@ def retrieve( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -237,8 +193,7 @@ def retrieve( Get machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -250,13 +205,12 @@ def retrieve( Example: ```python machine = client.machines.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get( path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( @@ -273,7 +227,6 @@ def update( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, - x_dedalus_org_id: 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, @@ -286,12 +239,11 @@ def update( Update machine Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. 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. vcpu: CPU in vCPUs. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -304,14 +256,13 @@ def update( Example: ```python machine = client.machines.update( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._patch( path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), body=maybe_transform( @@ -337,7 +288,6 @@ def delete( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -350,8 +300,7 @@ def delete( Destroy machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -364,14 +313,13 @@ def delete( Example: ```python machine = client.machines.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._delete( path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( @@ -384,66 +332,10 @@ def delete( cast_to=Machine, ) - def watch( - self, - *, - machine_id: str, - x_dedalus_org_id: str | Omit = omit, - last_event_id: 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, - ) -> Stream[Machine]: - """ - Streams machine lifecycle updates over Server-Sent Events. Each `status` event contains a full `LifecycleResponse` payload. The stream closes after the machine reaches its current desired state. - - Args: - machine_id: Machine identifier. - x_dedalus_org_id: Organization ID header applied to all DCS requests. - last_event_id: Optional resourceVersion bookmark used to resume a previous stream. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Stream[Machine]: Server-Sent Event stream (`text/event-stream`) of machine lifecycle updates. - - Example: - ```python - stream = client.machines.watch( - machine_id="machineID", - ) - - for machine in stream: - print(machine) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = { - **strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id, "Last-Event-ID": last_event_id}), - **(extra_headers or {}), - } - extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} - return self._get( - path_template("/v1/machines/{machine_id}/status/stream", **{"machine_id": machine_id}), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Machine, - stream=True, - stream_cls=Stream[Machine], - ) - def sleep( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -456,8 +348,7 @@ def sleep( Sleep a running machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -470,14 +361,13 @@ def sleep( Example: ```python machine = client.machines.sleep( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( path_template("/v1/machines/{machine_id}/sleep", **{"machine_id": machine_id}), options=make_request_options( @@ -494,7 +384,6 @@ def wake( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -507,8 +396,7 @@ def wake( Wake a sleeping machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -521,14 +409,13 @@ def wake( Example: ```python machine = client.machines.wake( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( path_template("/v1/machines/{machine_id}/wake", **{"machine_id": machine_id}), options=make_request_options( @@ -543,18 +430,6 @@ def wake( class AsyncMachinesResource(AsyncAPIResource): - @cached_property - def network(self) -> AsyncNetworkResource: - return AsyncNetworkResource(self._client) - - @cached_property - def artifacts(self) -> AsyncArtifactsResource: - return AsyncArtifactsResource(self._client) - - @cached_property - def ports(self) -> AsyncPortsResource: - return AsyncPortsResource(self._client) - @cached_property def ssh(self) -> AsyncSSHResource: return AsyncSSHResource(self._client) @@ -580,7 +455,6 @@ def list( *, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -594,7 +468,6 @@ def list( Args: limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -608,7 +481,6 @@ def list( page = client.machines.list() ``` """ - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( "/v1/machines", page=AsyncCursorPage[MachineListItem], @@ -630,7 +502,6 @@ async def create( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, - x_dedalus_org_id: 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, @@ -647,7 +518,6 @@ async def create( memory_mib: Memory in MiB. storage_gib: Storage in GiB. vcpu: CPU in vCPUs. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -668,7 +538,6 @@ async def create( ) ``` """ - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( "/v1/machines", body=await async_maybe_transform( @@ -694,7 +563,6 @@ async def retrieve( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -706,8 +574,7 @@ async def retrieve( Get machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -719,13 +586,12 @@ async def retrieve( Example: ```python machine = await client.machines.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._get( path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( @@ -742,7 +608,6 @@ async def update( memory_mib: int | Omit = omit, storage_gib: int | Omit = omit, vcpu: float | Omit = omit, - x_dedalus_org_id: 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, @@ -755,12 +620,11 @@ async def update( Update machine Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. 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. vcpu: CPU in vCPUs. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -773,14 +637,13 @@ async def update( Example: ```python machine = await client.machines.update( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._patch( path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), body=await async_maybe_transform( @@ -806,7 +669,6 @@ async def delete( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -819,8 +681,7 @@ async def delete( Destroy machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -833,14 +694,13 @@ async def delete( Example: ```python machine = await client.machines.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._delete( path_template("/v1/machines/{machine_id}", **{"machine_id": machine_id}), options=make_request_options( @@ -853,66 +713,10 @@ async def delete( cast_to=Machine, ) - async def watch( - self, - *, - machine_id: str, - x_dedalus_org_id: str | Omit = omit, - last_event_id: 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, - ) -> AsyncStream[Machine]: - """ - Streams machine lifecycle updates over Server-Sent Events. Each `status` event contains a full `LifecycleResponse` payload. The stream closes after the machine reaches its current desired state. - - Args: - machine_id: Machine identifier. - x_dedalus_org_id: Organization ID header applied to all DCS requests. - last_event_id: Optional resourceVersion bookmark used to resume a previous stream. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - AsyncStream[Machine]: Server-Sent Event stream (`text/event-stream`) of machine lifecycle updates. - - Example: - ```python - stream = await client.machines.watch( - machine_id="machineID", - ) - - async for machine in stream: - print(machine) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = { - **strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id, "Last-Event-ID": last_event_id}), - **(extra_headers or {}), - } - extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})} - return await self._get( - path_template("/v1/machines/{machine_id}/status/stream", **{"machine_id": machine_id}), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Machine, - stream=True, - stream_cls=AsyncStream[Machine], - ) - async def sleep( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -925,8 +729,7 @@ async def sleep( Sleep a running machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -939,14 +742,13 @@ async def sleep( Example: ```python machine = await client.machines.sleep( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( path_template("/v1/machines/{machine_id}/sleep", **{"machine_id": machine_id}), options=make_request_options( @@ -963,7 +765,6 @@ async def wake( self, *, machine_id: str, - x_dedalus_org_id: 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, @@ -976,8 +777,7 @@ async def wake( Wake a sleeping machine Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -990,14 +790,13 @@ async def wake( Example: ```python machine = await client.machines.wake( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( path_template("/v1/machines/{machine_id}/wake", **{"machine_id": machine_id}), options=make_request_options( @@ -1030,9 +829,6 @@ def __init__(self, machines: MachinesResource) -> None: self.delete = to_raw_response_wrapper( machines.delete, ) - self.watch = to_raw_response_wrapper( - machines.watch, - ) self.sleep = to_raw_response_wrapper( machines.sleep, ) @@ -1040,18 +836,6 @@ def __init__(self, machines: MachinesResource) -> None: machines.wake, ) - @cached_property - def network(self) -> NetworkResourceWithRawResponse: - return NetworkResourceWithRawResponse(self._machines.network) - - @cached_property - def artifacts(self) -> ArtifactsResourceWithRawResponse: - return ArtifactsResourceWithRawResponse(self._machines.artifacts) - - @cached_property - def ports(self) -> PortsResourceWithRawResponse: - return PortsResourceWithRawResponse(self._machines.ports) - @cached_property def ssh(self) -> SSHResourceWithRawResponse: return SSHResourceWithRawResponse(self._machines.ssh) @@ -1084,9 +868,6 @@ def __init__(self, machines: AsyncMachinesResource) -> None: self.delete = async_to_raw_response_wrapper( machines.delete, ) - self.watch = async_to_raw_response_wrapper( - machines.watch, - ) self.sleep = async_to_raw_response_wrapper( machines.sleep, ) @@ -1094,18 +875,6 @@ def __init__(self, machines: AsyncMachinesResource) -> None: machines.wake, ) - @cached_property - def network(self) -> AsyncNetworkResourceWithRawResponse: - return AsyncNetworkResourceWithRawResponse(self._machines.network) - - @cached_property - def artifacts(self) -> AsyncArtifactsResourceWithRawResponse: - return AsyncArtifactsResourceWithRawResponse(self._machines.artifacts) - - @cached_property - def ports(self) -> AsyncPortsResourceWithRawResponse: - return AsyncPortsResourceWithRawResponse(self._machines.ports) - @cached_property def ssh(self) -> AsyncSSHResourceWithRawResponse: return AsyncSSHResourceWithRawResponse(self._machines.ssh) @@ -1138,9 +907,6 @@ def __init__(self, machines: MachinesResource) -> None: self.delete = to_streamed_response_wrapper( machines.delete, ) - self.watch = to_streamed_response_wrapper( - machines.watch, - ) self.sleep = to_streamed_response_wrapper( machines.sleep, ) @@ -1148,18 +914,6 @@ def __init__(self, machines: MachinesResource) -> None: machines.wake, ) - @cached_property - def network(self) -> NetworkResourceWithStreamingResponse: - return NetworkResourceWithStreamingResponse(self._machines.network) - - @cached_property - def artifacts(self) -> ArtifactsResourceWithStreamingResponse: - return ArtifactsResourceWithStreamingResponse(self._machines.artifacts) - - @cached_property - def ports(self) -> PortsResourceWithStreamingResponse: - return PortsResourceWithStreamingResponse(self._machines.ports) - @cached_property def ssh(self) -> SSHResourceWithStreamingResponse: return SSHResourceWithStreamingResponse(self._machines.ssh) @@ -1192,9 +946,6 @@ def __init__(self, machines: AsyncMachinesResource) -> None: self.delete = async_to_streamed_response_wrapper( machines.delete, ) - self.watch = async_to_streamed_response_wrapper( - machines.watch, - ) self.sleep = async_to_streamed_response_wrapper( machines.sleep, ) @@ -1202,18 +953,6 @@ def __init__(self, machines: AsyncMachinesResource) -> None: machines.wake, ) - @cached_property - def network(self) -> AsyncNetworkResourceWithStreamingResponse: - return AsyncNetworkResourceWithStreamingResponse(self._machines.network) - - @cached_property - def artifacts(self) -> AsyncArtifactsResourceWithStreamingResponse: - return AsyncArtifactsResourceWithStreamingResponse(self._machines.artifacts) - - @cached_property - def ports(self) -> AsyncPortsResourceWithStreamingResponse: - return AsyncPortsResourceWithStreamingResponse(self._machines.ports) - @cached_property def ssh(self) -> AsyncSSHResourceWithStreamingResponse: return AsyncSSHResourceWithStreamingResponse(self._machines.ssh) diff --git a/src/dedalus_sdk/resources/machines/network.py b/src/dedalus_sdk/resources/machines/network.py deleted file mode 100644 index de66baf..0000000 --- a/src/dedalus_sdk/resources/machines/network.py +++ /dev/null @@ -1,164 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.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, strip_not_given -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options -from ...types.machines.machine_network import MachineNetwork - -__all__ = ["NetworkResource", "AsyncNetworkResource"] - - -class NetworkResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> NetworkResourceWithRawResponse: - return NetworkResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> NetworkResourceWithStreamingResponse: - return NetworkResourceWithStreamingResponse(self) - - def retrieve( - self, - *, - machine_id: str, - x_dedalus_org_id: 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, - ) -> MachineNetwork: - """ - Get machine network identity - - Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - MachineNetwork: OK - - Example: - ```python - network = client.machines.network.retrieve( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get( - path_template("/v1/machines/{machine_id}/network", **{"machine_id": machine_id}), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=MachineNetwork, - ) - - -class AsyncNetworkResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncNetworkResourceWithRawResponse: - return AsyncNetworkResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncNetworkResourceWithStreamingResponse: - return AsyncNetworkResourceWithStreamingResponse(self) - - async def retrieve( - self, - *, - machine_id: str, - x_dedalus_org_id: 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, - ) -> MachineNetwork: - """ - Get machine network identity - - Args: - machine_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - MachineNetwork: OK - - Example: - ```python - network = await client.machines.network.retrieve( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._get( - path_template("/v1/machines/{machine_id}/network", **{"machine_id": machine_id}), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=MachineNetwork, - ) - - -class NetworkResourceWithRawResponse: - def __init__(self, network: NetworkResource) -> None: - self._network = network - - self.retrieve = to_raw_response_wrapper( - network.retrieve, - ) - - -class AsyncNetworkResourceWithRawResponse: - def __init__(self, network: AsyncNetworkResource) -> None: - self._network = network - - self.retrieve = async_to_raw_response_wrapper( - network.retrieve, - ) - - -class NetworkResourceWithStreamingResponse: - def __init__(self, network: NetworkResource) -> None: - self._network = network - - self.retrieve = to_streamed_response_wrapper( - network.retrieve, - ) - - -class AsyncNetworkResourceWithStreamingResponse: - def __init__(self, network: AsyncNetworkResource) -> None: - self._network = network - - self.retrieve = async_to_streamed_response_wrapper( - network.retrieve, - ) diff --git a/src/dedalus_sdk/resources/machines/ports.py b/src/dedalus_sdk/resources/machines/ports.py deleted file mode 100644 index 40c87e8..0000000 --- a/src/dedalus_sdk/resources/machines/ports.py +++ /dev/null @@ -1,568 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -import httpx - -from typing_extensions import Literal - -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform, strip_not_given -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...pagination import SyncCursorPage, AsyncCursorPage -from ..._base_client import AsyncPaginator, make_request_options -from ...types.machines import port_list_params, port_create_params -from ...types.machines.port import Port - -__all__ = ["PortsResource", "AsyncPortsResource"] - - -class PortsResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> PortsResourceWithRawResponse: - return PortsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> PortsResourceWithStreamingResponse: - return PortsResourceWithStreamingResponse(self) - - def list( - self, - *, - machine_id: str, - limit: int | Omit = omit, - cursor: str | Omit = omit, - x_dedalus_org_id: 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, - ) -> SyncCursorPage[Port]: - """ - List ports - - Args: - machine_id: Path parameter. - limit: Query parameter. - cursor: Query parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - SyncCursorPage[Port]: OK - - Example: - ```python - page = client.machines.ports.list( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get_api_list( - path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), - page=SyncCursorPage[Port], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"limit": limit, "cursor": cursor}, port_list_params.PortListParams), - ), - model=Port, - method="get", - ) - - def create( - self, - *, - machine_id: str, - port: int, - protocol: Literal["http", "https"] | Omit = omit, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Port: - """ - Create port - - Args: - machine_id: Path parameter. - port: Body parameter. - protocol: Body parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Port: OK - - Example: - ```python - port = client.machines.ports.create( - machine_id="machineID", - port=0, - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._post( - path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), - body=maybe_transform( - { - "port": port, - "protocol": protocol, - }, - port_create_params.PortCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Port, - ) - - def retrieve( - self, - *, - machine_id: str, - port_id: str, - x_dedalus_org_id: 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, - ) -> Port: - """ - Get port - - Args: - machine_id: Path parameter. - port_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Port: OK - - Example: - ```python - port = client.machines.ports.retrieve( - machine_id="machineID", - port_id="portID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if port_id is None or (isinstance(port_id, str) and not port_id): - raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get( - path_template( - "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Port, - ) - - def delete( - self, - *, - machine_id: str, - port_id: str, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Port: - """ - Delete port - - Args: - machine_id: Path parameter. - port_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Port: OK - - Example: - ```python - port = client.machines.ports.delete( - machine_id="machineID", - port_id="portID", - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if port_id is None or (isinstance(port_id, str) and not port_id): - raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._delete( - path_template( - "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Port, - ) - - -class AsyncPortsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncPortsResourceWithRawResponse: - return AsyncPortsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncPortsResourceWithStreamingResponse: - return AsyncPortsResourceWithStreamingResponse(self) - - def list( - self, - *, - machine_id: str, - limit: int | Omit = omit, - cursor: str | Omit = omit, - x_dedalus_org_id: 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, - ) -> AsyncPaginator[Port, AsyncCursorPage[Port]]: - """ - List ports - - Args: - machine_id: Path parameter. - limit: Query parameter. - cursor: Query parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - AsyncPaginator[Port, AsyncCursorPage[Port]]: OK - - Example: - ```python - page = client.machines.ports.list( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get_api_list( - path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), - page=AsyncCursorPage[Port], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"limit": limit, "cursor": cursor}, port_list_params.PortListParams), - ), - model=Port, - method="get", - ) - - async def create( - self, - *, - machine_id: str, - port: int, - protocol: Literal["http", "https"] | Omit = omit, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Port: - """ - Create port - - Args: - machine_id: Path parameter. - port: Body parameter. - protocol: Body parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Port: OK - - Example: - ```python - port = await client.machines.ports.create( - machine_id="machineID", - port=0, - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._post( - path_template("/v1/machines/{machine_id}/ports", **{"machine_id": machine_id}), - body=await async_maybe_transform( - { - "port": port, - "protocol": protocol, - }, - port_create_params.PortCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Port, - ) - - async def retrieve( - self, - *, - machine_id: str, - port_id: str, - x_dedalus_org_id: 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, - ) -> Port: - """ - Get port - - Args: - machine_id: Path parameter. - port_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Port: OK - - Example: - ```python - port = await client.machines.ports.retrieve( - machine_id="machineID", - port_id="portID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if port_id is None or (isinstance(port_id, str) and not port_id): - raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._get( - path_template( - "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Port, - ) - - async def delete( - self, - *, - machine_id: str, - port_id: str, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Port: - """ - Delete port - - Args: - machine_id: Path parameter. - port_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Port: OK - - Example: - ```python - port = await client.machines.ports.delete( - machine_id="machineID", - port_id="portID", - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if port_id is None or (isinstance(port_id, str) and not port_id): - raise ValueError(f"Expected a non-empty value for `port_id` but received {port_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._delete( - path_template( - "/v1/machines/{machine_id}/ports/{port_id}", **{"machine_id": machine_id, "port_id": port_id} - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Port, - ) - - -class PortsResourceWithRawResponse: - def __init__(self, ports: PortsResource) -> None: - self._ports = ports - - self.list = to_raw_response_wrapper( - ports.list, - ) - self.create = to_raw_response_wrapper( - ports.create, - ) - self.retrieve = to_raw_response_wrapper( - ports.retrieve, - ) - self.delete = to_raw_response_wrapper( - ports.delete, - ) - - -class AsyncPortsResourceWithRawResponse: - def __init__(self, ports: AsyncPortsResource) -> None: - self._ports = ports - - self.list = async_to_raw_response_wrapper( - ports.list, - ) - self.create = async_to_raw_response_wrapper( - ports.create, - ) - self.retrieve = async_to_raw_response_wrapper( - ports.retrieve, - ) - self.delete = async_to_raw_response_wrapper( - ports.delete, - ) - - -class PortsResourceWithStreamingResponse: - def __init__(self, ports: PortsResource) -> None: - self._ports = ports - - self.list = to_streamed_response_wrapper( - ports.list, - ) - self.create = to_streamed_response_wrapper( - ports.create, - ) - self.retrieve = to_streamed_response_wrapper( - ports.retrieve, - ) - self.delete = to_streamed_response_wrapper( - ports.delete, - ) - - -class AsyncPortsResourceWithStreamingResponse: - def __init__(self, ports: AsyncPortsResource) -> None: - self._ports = ports - - self.list = async_to_streamed_response_wrapper( - ports.list, - ) - self.create = async_to_streamed_response_wrapper( - ports.create, - ) - self.retrieve = async_to_streamed_response_wrapper( - ports.retrieve, - ) - self.delete = async_to_streamed_response_wrapper( - ports.delete, - ) diff --git a/src/dedalus_sdk/resources/machines/ssh.py b/src/dedalus_sdk/resources/machines/ssh.py index 64bc0ff..f3f6b06 100644 --- a/src/dedalus_sdk/resources/machines/ssh.py +++ b/src/dedalus_sdk/resources/machines/ssh.py @@ -5,7 +5,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform, strip_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 ( @@ -37,7 +37,6 @@ def list( machine_id: str, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -49,10 +48,9 @@ def list( List SSH sessions Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -64,13 +62,12 @@ def list( Example: ```python page = client.machines.ssh.list( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), page=SyncCursorPage[SSHSession], @@ -90,7 +87,6 @@ def create( *, machine_id: str, public_key: str, - x_dedalus_org_id: 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, @@ -103,9 +99,8 @@ def create( Create SSH session Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. public_key: Body parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -118,7 +113,7 @@ def create( Example: ```python ssh = client.machines.ssh.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", public_key="", idempotency_key="", ) @@ -126,7 +121,6 @@ def create( """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._post( path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), body=maybe_transform( @@ -148,7 +142,6 @@ def retrieve( *, machine_id: str, session_id: str, - x_dedalus_org_id: 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, @@ -160,9 +153,8 @@ def retrieve( Get SSH session Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. session_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -174,7 +166,7 @@ def retrieve( Example: ```python ssh = client.machines.ssh.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", ) ``` @@ -183,7 +175,6 @@ def retrieve( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if session_id is None or (isinstance(session_id, str) and not session_id): raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get( path_template( "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} @@ -199,7 +190,6 @@ def delete( *, machine_id: str, session_id: str, - x_dedalus_org_id: 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, @@ -212,9 +202,8 @@ def delete( Delete SSH session Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. session_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -227,7 +216,7 @@ def delete( Example: ```python ssh = client.machines.ssh.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", idempotency_key="", ) @@ -237,7 +226,6 @@ def delete( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if session_id is None or (isinstance(session_id, str) and not session_id): raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._delete( path_template( "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} @@ -268,7 +256,6 @@ def list( machine_id: str, limit: int | Omit = omit, cursor: str | Omit = omit, - x_dedalus_org_id: 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, @@ -280,10 +267,9 @@ def list( List SSH sessions Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. limit: Query parameter. cursor: Query parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -295,13 +281,12 @@ def list( Example: ```python page = client.machines.ssh.list( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) ``` """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return self._get_api_list( path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), page=AsyncCursorPage[SSHSession], @@ -321,7 +306,6 @@ async def create( *, machine_id: str, public_key: str, - x_dedalus_org_id: 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, @@ -334,9 +318,8 @@ async def create( Create SSH session Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. public_key: Body parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -349,7 +332,7 @@ async def create( Example: ```python ssh = await client.machines.ssh.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", public_key="", idempotency_key="", ) @@ -357,7 +340,6 @@ async def create( """ if machine_id is None or (isinstance(machine_id, str) and not machine_id): raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._post( path_template("/v1/machines/{machine_id}/ssh", **{"machine_id": machine_id}), body=await async_maybe_transform( @@ -379,7 +361,6 @@ async def retrieve( *, machine_id: str, session_id: str, - x_dedalus_org_id: 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, @@ -391,9 +372,8 @@ async def retrieve( Get SSH session Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. session_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -405,7 +385,7 @@ async def retrieve( Example: ```python ssh = await client.machines.ssh.retrieve( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", ) ``` @@ -414,7 +394,6 @@ async def retrieve( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if session_id is None or (isinstance(session_id, str) and not session_id): raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._get( path_template( "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} @@ -430,7 +409,6 @@ async def delete( *, machine_id: str, session_id: str, - x_dedalus_org_id: 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, @@ -443,9 +421,8 @@ async def delete( Delete SSH session Args: - machine_id: Path parameter. + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. session_id: Path parameter. - x_dedalus_org_id: Header parameter. extra_headers: Send extra headers with the request. extra_query: Send extra query parameters with the request. extra_body: Send extra JSON properties with the request. @@ -458,7 +435,7 @@ async def delete( Example: ```python ssh = await client.machines.ssh.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", idempotency_key="", ) @@ -468,7 +445,6 @@ async def delete( raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") if session_id is None or (isinstance(session_id, str) and not session_id): raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} return await self._delete( path_template( "/v1/machines/{machine_id}/ssh/{session_id}", **{"machine_id": machine_id, "session_id": session_id} diff --git a/src/dedalus_sdk/resources/machines/terminals/terminals.py b/src/dedalus_sdk/resources/machines/terminals/terminals.py index f2a95a9..671fdfb 100644 --- a/src/dedalus_sdk/resources/machines/terminals/terminals.py +++ b/src/dedalus_sdk/resources/machines/terminals/terminals.py @@ -4,11 +4,9 @@ import httpx -from typing import Dict from typing import Callable -from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ...._utils import path_template, maybe_transform, async_maybe_transform, strip_not_given +from ...._types import Query, Headers from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import ( @@ -17,10 +15,7 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ....pagination import SyncCursorPage, AsyncCursorPage -from ...._base_client import AsyncPaginator, make_request_options -from ....types.machines import terminal_list_params, terminal_create_params -from ....types.machines.terminal import Terminal +from ...._base_client import make_request_options from ....types.websocket_connection_options import WebSocketConnectionOptions from ....types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides from .ws import ( @@ -42,244 +37,6 @@ def with_raw_response(self) -> TerminalsResourceWithRawResponse: def with_streaming_response(self) -> TerminalsResourceWithStreamingResponse: return TerminalsResourceWithStreamingResponse(self) - def list( - self, - *, - machine_id: str, - limit: int | Omit = omit, - cursor: str | Omit = omit, - x_dedalus_org_id: 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, - ) -> SyncCursorPage[Terminal]: - """ - List terminals - - Args: - machine_id: Path parameter. - limit: Query parameter. - cursor: Query parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - SyncCursorPage[Terminal]: OK - - Example: - ```python - page = client.machines.terminals.list( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get_api_list( - path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), - page=SyncCursorPage[Terminal], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"limit": limit, "cursor": cursor}, terminal_list_params.TerminalListParams), - ), - model=Terminal, - method="get", - ) - - def create( - self, - *, - machine_id: str, - cwd: str | Omit = omit, - env: Dict[str, str] | Omit = omit, - height: int, - shell: str | Omit = omit, - width: int, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Terminal: - """ - Create terminal - - Args: - machine_id: Path parameter. - cwd: Body parameter. - env: Body parameter. - height: Body parameter. - shell: Body parameter. - width: Body parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Terminal: OK - - Example: - ```python - terminal = client.machines.terminals.create( - machine_id="machineID", - height=0, - width=0, - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._post( - path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), - body=maybe_transform( - { - "cwd": cwd, - "env": env, - "height": height, - "shell": shell, - "width": width, - }, - terminal_create_params.TerminalCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Terminal, - ) - - def retrieve( - self, - *, - machine_id: str, - terminal_id: str, - x_dedalus_org_id: 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, - ) -> Terminal: - """ - Get terminal - - Args: - machine_id: Path parameter. - terminal_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Terminal: OK - - Example: - ```python - terminal = client.machines.terminals.retrieve( - machine_id="machineID", - terminal_id="terminalID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): - raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get( - path_template( - "/v1/machines/{machine_id}/terminals/{terminal_id}", - **{"machine_id": machine_id, "terminal_id": terminal_id}, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Terminal, - ) - - def delete( - self, - *, - machine_id: str, - terminal_id: str, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Terminal: - """ - Delete terminal - - Args: - machine_id: Path parameter. - terminal_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Terminal: OK - - Example: - ```python - terminal = client.machines.terminals.delete( - machine_id="machineID", - terminal_id="terminalID", - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): - raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._delete( - path_template( - "/v1/machines/{machine_id}/terminals/{terminal_id}", - **{"machine_id": machine_id, "terminal_id": terminal_id}, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Terminal, - ) - def connect( self, *, @@ -318,244 +75,6 @@ def with_raw_response(self) -> AsyncTerminalsResourceWithRawResponse: def with_streaming_response(self) -> AsyncTerminalsResourceWithStreamingResponse: return AsyncTerminalsResourceWithStreamingResponse(self) - def list( - self, - *, - machine_id: str, - limit: int | Omit = omit, - cursor: str | Omit = omit, - x_dedalus_org_id: 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, - ) -> AsyncPaginator[Terminal, AsyncCursorPage[Terminal]]: - """ - List terminals - - Args: - machine_id: Path parameter. - limit: Query parameter. - cursor: Query parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - AsyncPaginator[Terminal, AsyncCursorPage[Terminal]]: OK - - Example: - ```python - page = client.machines.terminals.list( - machine_id="machineID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get_api_list( - path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), - page=AsyncCursorPage[Terminal], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"limit": limit, "cursor": cursor}, terminal_list_params.TerminalListParams), - ), - model=Terminal, - method="get", - ) - - async def create( - self, - *, - machine_id: str, - cwd: str | Omit = omit, - env: Dict[str, str] | Omit = omit, - height: int, - shell: str | Omit = omit, - width: int, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Terminal: - """ - Create terminal - - Args: - machine_id: Path parameter. - cwd: Body parameter. - env: Body parameter. - height: Body parameter. - shell: Body parameter. - width: Body parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Terminal: OK - - Example: - ```python - terminal = await client.machines.terminals.create( - machine_id="machineID", - height=0, - width=0, - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._post( - path_template("/v1/machines/{machine_id}/terminals", **{"machine_id": machine_id}), - body=await async_maybe_transform( - { - "cwd": cwd, - "env": env, - "height": height, - "shell": shell, - "width": width, - }, - terminal_create_params.TerminalCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Terminal, - ) - - async def retrieve( - self, - *, - machine_id: str, - terminal_id: str, - x_dedalus_org_id: 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, - ) -> Terminal: - """ - Get terminal - - Args: - machine_id: Path parameter. - terminal_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Terminal: OK - - Example: - ```python - terminal = await client.machines.terminals.retrieve( - machine_id="machineID", - terminal_id="terminalID", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): - raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._get( - path_template( - "/v1/machines/{machine_id}/terminals/{terminal_id}", - **{"machine_id": machine_id, "terminal_id": terminal_id}, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Terminal, - ) - - async def delete( - self, - *, - machine_id: str, - terminal_id: str, - x_dedalus_org_id: 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, - idempotency_key: str | None = None, - ) -> Terminal: - """ - Delete terminal - - Args: - machine_id: Path parameter. - terminal_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - idempotency_key: Override or provide the idempotency key for this request. - - Returns: - Terminal: OK - - Example: - ```python - terminal = await client.machines.terminals.delete( - machine_id="machineID", - terminal_id="terminalID", - idempotency_key="", - ) - ``` - """ - if machine_id is None or (isinstance(machine_id, str) and not machine_id): - raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") - if terminal_id is None or (isinstance(terminal_id, str) and not terminal_id): - raise ValueError(f"Expected a non-empty value for `terminal_id` but received {terminal_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._delete( - path_template( - "/v1/machines/{machine_id}/terminals/{terminal_id}", - **{"machine_id": machine_id, "terminal_id": terminal_id}, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - idempotency_key=idempotency_key, - ), - cast_to=Terminal, - ) - def connect( self, *, @@ -589,69 +108,17 @@ class TerminalsResourceWithRawResponse: def __init__(self, terminals: TerminalsResource) -> None: self._terminals = terminals - self.list = to_raw_response_wrapper( - terminals.list, - ) - self.create = to_raw_response_wrapper( - terminals.create, - ) - self.retrieve = to_raw_response_wrapper( - terminals.retrieve, - ) - self.delete = to_raw_response_wrapper( - terminals.delete, - ) - class AsyncTerminalsResourceWithRawResponse: def __init__(self, terminals: AsyncTerminalsResource) -> None: self._terminals = terminals - self.list = async_to_raw_response_wrapper( - terminals.list, - ) - self.create = async_to_raw_response_wrapper( - terminals.create, - ) - self.retrieve = async_to_raw_response_wrapper( - terminals.retrieve, - ) - self.delete = async_to_raw_response_wrapper( - terminals.delete, - ) - class TerminalsResourceWithStreamingResponse: def __init__(self, terminals: TerminalsResource) -> None: self._terminals = terminals - self.list = to_streamed_response_wrapper( - terminals.list, - ) - self.create = to_streamed_response_wrapper( - terminals.create, - ) - self.retrieve = to_streamed_response_wrapper( - terminals.retrieve, - ) - self.delete = to_streamed_response_wrapper( - terminals.delete, - ) - class AsyncTerminalsResourceWithStreamingResponse: def __init__(self, terminals: AsyncTerminalsResource) -> None: self._terminals = terminals - - self.list = async_to_streamed_response_wrapper( - terminals.list, - ) - self.create = async_to_streamed_response_wrapper( - terminals.create, - ) - self.retrieve = async_to_streamed_response_wrapper( - terminals.retrieve, - ) - self.delete = async_to_streamed_response_wrapper( - terminals.delete, - ) diff --git a/src/dedalus_sdk/resources/machines/terminals/ws.py b/src/dedalus_sdk/resources/machines/terminals/ws.py index d168d83..f92dd94 100644 --- a/src/dedalus_sdk/resources/machines/terminals/ws.py +++ b/src/dedalus_sdk/resources/machines/terminals/ws.py @@ -21,9 +21,9 @@ from ...._utils import path_template, maybe_transform, async_maybe_transform from ....types.websocket_connection_options import WebSocketConnectionOptions from ....types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides, is_recoverable_close -from ....types.machines.terminal_client_event import TerminalClientEvent -from ....types.machines.terminal_client_event_param import TerminalClientEventParam -from ....types.machines.terminal_server_event import TerminalServerEvent +from ....types.machines.connect_client_event import ConnectClientEvent +from ....types.machines.connect_client_event_param import ConnectClientEventParam +from ....types.machines.connect_server_event import ConnectServerEvent if TYPE_CHECKING: from websockets.sync.client import ClientConnection as WebSocketConnection @@ -77,7 +77,7 @@ def __init__( self._send_queue = send_queue or SendQueue() self._event_handler_registry = EventHandlerRegistry(use_lock=True) - def __iter__(self) -> Iterator[TerminalServerEvent]: + def __iter__(self) -> Iterator[ConnectServerEvent]: """Yield events until the connection closes.""" from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError @@ -96,7 +96,7 @@ def __iter__(self) -> Iterator[TerminalServerEvent]: ) from exc raise - def recv(self) -> TerminalServerEvent: + def recv(self) -> ConnectServerEvent: """Receive and parse the next websocket message.""" return self.parse_event(self.recv_bytes()) @@ -106,11 +106,11 @@ def recv_bytes(self) -> bytes: log.debug("Received WebSocket message: %s", message) return message - def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) - else json.dumps(maybe_transform(event, TerminalClientEventParam)) + else json.dumps(maybe_transform(event, ConnectClientEventParam)) ) if self._is_reconnecting: self._send_queue.enqueue(data) @@ -132,10 +132,10 @@ def close(self, *, code: int = 1000, reason: str = "") -> None: self._intentionally_closed = True self._connection.close(code=code, reason=reason) - def parse_event(self, data: str | bytes) -> TerminalServerEvent: + def parse_event(self, data: str | bytes) -> ConnectServerEvent: """Convert a raw websocket message into the generated server event type.""" return cast( - TerminalServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, TerminalServerEvent)) + ConnectServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, ConnectServerEvent)) ) def _reconnect(self, exc: Exception) -> bool: @@ -280,7 +280,7 @@ def __init__( self._send_queue = send_queue or SendQueue() self._event_handler_registry = EventHandlerRegistry(use_lock=False) - async def __aiter__(self) -> AsyncIterator[TerminalServerEvent]: + async def __aiter__(self) -> AsyncIterator[ConnectServerEvent]: """Yield events until the connection closes.""" from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError @@ -299,7 +299,7 @@ async def __aiter__(self) -> AsyncIterator[TerminalServerEvent]: ) from exc raise - async def recv(self) -> TerminalServerEvent: + async def recv(self) -> ConnectServerEvent: """Receive and parse the next websocket message.""" return self.parse_event(await self.recv_bytes()) @@ -309,11 +309,11 @@ async def recv_bytes(self) -> bytes: log.debug("Received WebSocket message: %s", message) return message - async def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + async def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) - else json.dumps(await async_maybe_transform(event, TerminalClientEventParam)) + else json.dumps(await async_maybe_transform(event, ConnectClientEventParam)) ) if self._is_reconnecting: self._send_queue.enqueue(data) @@ -335,10 +335,10 @@ async def close(self, *, code: int = 1000, reason: str = "") -> None: self._intentionally_closed = True await self._connection.close(code=code, reason=reason) - def parse_event(self, data: str | bytes) -> TerminalServerEvent: + def parse_event(self, data: str | bytes) -> ConnectServerEvent: """Convert a raw websocket message into the generated server event type.""" return cast( - TerminalServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, TerminalServerEvent)) + ConnectServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, ConnectServerEvent)) ) async def _reconnect(self, exc: Exception) -> bool: @@ -498,12 +498,12 @@ def __init__( self.__send_queue = SendQueue(max_bytes=max_queue_size) self.__event_handler_registry = EventHandlerRegistry(use_lock=True) - def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: """Queue a message to send as soon as the websocket opens.""" data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) - else json.dumps(maybe_transform(event, TerminalClientEventParam)) + else json.dumps(maybe_transform(event, ConnectClientEventParam)) ) self.__send_queue.enqueue(data) @@ -656,12 +656,12 @@ def __init__( self.__send_queue = SendQueue(max_bytes=max_queue_size) self.__event_handler_registry = EventHandlerRegistry(use_lock=False) - def send(self, event: TerminalClientEvent | TerminalClientEventParam) -> None: + def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: """Queue a message to send as soon as the websocket opens.""" data = ( event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) if isinstance(event, BaseModel) - else json.dumps(maybe_transform(event, TerminalClientEventParam)) + else json.dumps(maybe_transform(event, ConnectClientEventParam)) ) self.__send_queue.enqueue(data) diff --git a/src/dedalus_sdk/resources/networks.py b/src/dedalus_sdk/resources/networks.py deleted file mode 100644 index fc9b768..0000000 --- a/src/dedalus_sdk/resources/networks.py +++ /dev/null @@ -1,164 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.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, strip_not_given -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from .._base_client import make_request_options -from ..types.network import Network - -__all__ = ["NetworksResource", "AsyncNetworksResource"] - - -class NetworksResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> NetworksResourceWithRawResponse: - return NetworksResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> NetworksResourceWithStreamingResponse: - return NetworksResourceWithStreamingResponse(self) - - def retrieve( - self, - *, - network_id: str, - x_dedalus_org_id: 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, - ) -> Network: - """ - Get network details - - Args: - network_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Network: OK - - Example: - ```python - network = client.networks.retrieve( - network_id="networkID", - ) - ``` - """ - if network_id is None or (isinstance(network_id, str) and not network_id): - raise ValueError(f"Expected a non-empty value for `network_id` but received {network_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return self._get( - path_template("/v1/networks/{network_id}", **{"network_id": network_id}), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Network, - ) - - -class AsyncNetworksResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncNetworksResourceWithRawResponse: - return AsyncNetworksResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncNetworksResourceWithStreamingResponse: - return AsyncNetworksResourceWithStreamingResponse(self) - - async def retrieve( - self, - *, - network_id: str, - x_dedalus_org_id: 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, - ) -> Network: - """ - Get network details - - Args: - network_id: Path parameter. - x_dedalus_org_id: Header parameter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - Network: OK - - Example: - ```python - network = await client.networks.retrieve( - network_id="networkID", - ) - ``` - """ - if network_id is None or (isinstance(network_id, str) and not network_id): - raise ValueError(f"Expected a non-empty value for `network_id` but received {network_id!r}") - extra_headers = {**strip_not_given({"X-Dedalus-Org-Id": x_dedalus_org_id}), **(extra_headers or {})} - return await self._get( - path_template("/v1/networks/{network_id}", **{"network_id": network_id}), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Network, - ) - - -class NetworksResourceWithRawResponse: - def __init__(self, networks: NetworksResource) -> None: - self._networks = networks - - self.retrieve = to_raw_response_wrapper( - networks.retrieve, - ) - - -class AsyncNetworksResourceWithRawResponse: - def __init__(self, networks: AsyncNetworksResource) -> None: - self._networks = networks - - self.retrieve = async_to_raw_response_wrapper( - networks.retrieve, - ) - - -class NetworksResourceWithStreamingResponse: - def __init__(self, networks: NetworksResource) -> None: - self._networks = networks - - self.retrieve = to_streamed_response_wrapper( - networks.retrieve, - ) - - -class AsyncNetworksResourceWithStreamingResponse: - def __init__(self, networks: AsyncNetworksResource) -> None: - self._networks = networks - - self.retrieve = async_to_streamed_response_wrapper( - networks.retrieve, - ) diff --git a/src/dedalus_sdk/resources/usage.py b/src/dedalus_sdk/resources/usage.py deleted file mode 100644 index 02b235f..0000000 --- a/src/dedalus_sdk/resources/usage.py +++ /dev/null @@ -1,393 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -import httpx - -from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from .._base_client import make_request_options -from ..types.org_usage import OrgUsage -from ..types import usage_retrieve_params, usage_machine_compute_params, usage_machine_storage_params -from ..types.machine_compute_usage import MachineComputeUsage -from ..types.machine_storage_usage import MachineStorageUsage - -__all__ = ["UsageResource", "AsyncUsageResource"] - - -class UsageResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> UsageResourceWithRawResponse: - return UsageResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> UsageResourceWithStreamingResponse: - return UsageResourceWithStreamingResponse(self) - - def retrieve( - self, - *, - 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 usage summary - - Args: - period_start: Billing period start (YYYY-MM-DD). Defaults to first of current month. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - OrgUsage: OK - - Example: - ```python - usage = client.usage.retrieve() - ``` - """ - return self._get( - "/v1/usage", - 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 machine_compute( - self, - *, - period_start: str | Omit = omit, - period_end: str | Omit = omit, - machine_id: str | Omit = omit, - granularity: 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, - ) -> MachineComputeUsage: - """ - List machine compute usage breakdown - - Args: - period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. - period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. - machine_id: Optional machine ID filter. - granularity: Usage breakdown granularity: hour or day. Defaults to hour. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - MachineComputeUsage: OK - - Example: - ```python - usage = client.usage.machine_compute() - ``` - """ - return self._get( - "/v1/usage/machines/compute", - 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, - "period_end": period_end, - "machine_id": machine_id, - "granularity": granularity, - }, - usage_machine_compute_params.UsageMachineComputeParams, - ), - ), - cast_to=MachineComputeUsage, - ) - - def machine_storage( - self, - *, - period_start: str | Omit = omit, - period_end: str | Omit = omit, - machine_id: 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 breakdown - - Args: - period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. - period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. - machine_id: Optional machine ID filter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - MachineStorageUsage: OK - - Example: - ```python - usage = client.usage.machine_storage() - ``` - """ - return self._get( - "/v1/usage/machines/storage", - 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, "period_end": period_end, "machine_id": machine_id}, - usage_machine_storage_params.UsageMachineStorageParams, - ), - ), - cast_to=MachineStorageUsage, - ) - - -class AsyncUsageResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: - return AsyncUsageResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: - return AsyncUsageResourceWithStreamingResponse(self) - - async def retrieve( - self, - *, - 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 usage summary - - Args: - period_start: Billing period start (YYYY-MM-DD). Defaults to first of current month. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - OrgUsage: OK - - Example: - ```python - usage = await client.usage.retrieve() - ``` - """ - return await self._get( - "/v1/usage", - 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 machine_compute( - self, - *, - period_start: str | Omit = omit, - period_end: str | Omit = omit, - machine_id: str | Omit = omit, - granularity: 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, - ) -> MachineComputeUsage: - """ - List machine compute usage breakdown - - Args: - period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. - period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. - machine_id: Optional machine ID filter. - granularity: Usage breakdown granularity: hour or day. Defaults to hour. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - MachineComputeUsage: OK - - Example: - ```python - usage = await client.usage.machine_compute() - ``` - """ - return await self._get( - "/v1/usage/machines/compute", - 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, - "period_end": period_end, - "machine_id": machine_id, - "granularity": granularity, - }, - usage_machine_compute_params.UsageMachineComputeParams, - ), - ), - cast_to=MachineComputeUsage, - ) - - async def machine_storage( - self, - *, - period_start: str | Omit = omit, - period_end: str | Omit = omit, - machine_id: 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 breakdown - - Args: - period_start: Usage period start (YYYY-MM-DD). Defaults to first of current month. - period_end: Last UTC usage date to include (YYYY-MM-DD). Defaults to current time. - machine_id: Optional machine ID filter. - extra_headers: Send extra headers with the request. - extra_query: Send extra query parameters with the request. - extra_body: Send extra JSON properties with the request. - timeout: Override the client-level default timeout for this request, in seconds. - - Returns: - MachineStorageUsage: OK - - Example: - ```python - usage = await client.usage.machine_storage() - ``` - """ - return await self._get( - "/v1/usage/machines/storage", - 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, "period_end": period_end, "machine_id": machine_id}, - usage_machine_storage_params.UsageMachineStorageParams, - ), - ), - cast_to=MachineStorageUsage, - ) - - -class UsageResourceWithRawResponse: - def __init__(self, usage: UsageResource) -> None: - self._usage = usage - - self.retrieve = to_raw_response_wrapper( - usage.retrieve, - ) - self.machine_compute = to_raw_response_wrapper( - usage.machine_compute, - ) - self.machine_storage = to_raw_response_wrapper( - usage.machine_storage, - ) - - -class AsyncUsageResourceWithRawResponse: - def __init__(self, usage: AsyncUsageResource) -> None: - self._usage = usage - - self.retrieve = async_to_raw_response_wrapper( - usage.retrieve, - ) - self.machine_compute = async_to_raw_response_wrapper( - usage.machine_compute, - ) - self.machine_storage = async_to_raw_response_wrapper( - usage.machine_storage, - ) - - -class UsageResourceWithStreamingResponse: - def __init__(self, usage: UsageResource) -> None: - self._usage = usage - - self.retrieve = to_streamed_response_wrapper( - usage.retrieve, - ) - self.machine_compute = to_streamed_response_wrapper( - usage.machine_compute, - ) - self.machine_storage = to_streamed_response_wrapper( - usage.machine_storage, - ) - - -class AsyncUsageResourceWithStreamingResponse: - def __init__(self, usage: AsyncUsageResource) -> None: - self._usage = usage - - self.retrieve = async_to_streamed_response_wrapper( - usage.retrieve, - ) - self.machine_compute = async_to_streamed_response_wrapper( - usage.machine_compute, - ) - self.machine_storage = async_to_streamed_response_wrapper( - usage.machine_storage, - ) diff --git a/src/dedalus_sdk/types/__init__.py b/src/dedalus_sdk/types/__init__.py index ab76b6d..462bf73 100644 --- a/src/dedalus_sdk/types/__init__.py +++ b/src/dedalus_sdk/types/__init__.py @@ -4,22 +4,12 @@ from .machine import Machine as Machine from .lifecycle_status import LifecycleStatus as LifecycleStatus -from .machine_compute_usage import MachineComputeUsage as MachineComputeUsage -from .machine_compute_usage_row import MachineComputeUsageRow as MachineComputeUsageRow from .machine_list_item import MachineListItem as MachineListItem from .machine_list import MachineList as MachineList -from .machine_storage_usage import MachineStorageUsage as MachineStorageUsage -from .machine_storage_usage_row import MachineStorageUsageRow as MachineStorageUsageRow -from .network_gateway import NetworkGateway as NetworkGateway -from .network import Network as Network -from .org_usage import OrgUsage as OrgUsage from .machine_list_params import MachineListParams as MachineListParams from .machine_create_params import MachineCreateParams as MachineCreateParams from .machine_retrieve_response import MachineRetrieveResponse as MachineRetrieveResponse from .machine_update_params import MachineUpdateParams as MachineUpdateParams -from .usage_retrieve_params import UsageRetrieveParams as UsageRetrieveParams -from .usage_machine_compute_params import UsageMachineComputeParams as UsageMachineComputeParams -from .usage_machine_storage_params import UsageMachineStorageParams as UsageMachineStorageParams from .websocket_connection_options import WebSocketConnectionOptions as WebSocketConnectionOptions from .websocket_reconnection import ( ReconnectingEvent as ReconnectingEvent, diff --git a/src/dedalus_sdk/types/lifecycle_status.py b/src/dedalus_sdk/types/lifecycle_status.py index fddc07a..fe2ae8c 100644 --- a/src/dedalus_sdk/types/lifecycle_status.py +++ b/src/dedalus_sdk/types/lifecycle_status.py @@ -16,6 +16,21 @@ class LifecycleStatus(BaseModel): last_transition_at: datetime + memory_assigned_mib: Optional[int] = None + """Last confirmed RAM allocation for the current running generation. Absent when the allocation is unknown or no longer current.""" + + memory_configured_mib: int + """Accepted RAM maximum, including completed automatic increases.""" + + memory_last_autoresized_at: Optional[datetime] = None + """Time of the latest confirmed automatic RAM increase. Does not include explicit resizing or a complete change history.""" + + memory_resize_state: Optional[Literal["stable", "error", "pending_capacity"]] = None + """Resize progress reported by the current runtime. A pending automatic target may not yet be applied by that runtime.""" + + memory_target_mib: Optional[int] = None + """Pending automatic RAM target, or the current runtime target when no automatic target is pending.""" + phase: Literal[ "accepted", "placement_pending", diff --git a/src/dedalus_sdk/types/machine_compute_usage.py b/src/dedalus_sdk/types/machine_compute_usage.py deleted file mode 100644 index e6e5d82..0000000 --- a/src/dedalus_sdk/types/machine_compute_usage.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import List, Optional -from datetime import datetime - -from .._models import BaseModel - -from .machine_compute_usage_row import MachineComputeUsageRow - -__all__ = ["MachineComputeUsage"] - - -class MachineComputeUsage(BaseModel): - granularity: str - """Usage breakdown granularity used for rows: hour or day.""" - - period_end: datetime - """Exclusive usage period end.""" - - period_start: datetime - """Inclusive usage period start.""" - - rows: Optional[List[MachineComputeUsageRow]] = None - """Machine-level compute usage breakdown rows.""" diff --git a/src/dedalus_sdk/types/machine_compute_usage_row.py b/src/dedalus_sdk/types/machine_compute_usage_row.py deleted file mode 100644 index 3df4d33..0000000 --- a/src/dedalus_sdk/types/machine_compute_usage_row.py +++ /dev/null @@ -1,52 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import List, Optional -from datetime import datetime - -from .._models import BaseModel - -__all__ = ["MachineComputeUsageRow"] - - -class MachineComputeUsageRow(BaseModel): - awake_seconds: int - """Machine-awake seconds in this bucket.""" - - bucket_end: datetime - """Exclusive usage bucket end.""" - - bucket_start: datetime - """Inclusive usage bucket start.""" - - cpu_millicore_seconds: int - """Requested vCPU millicores multiplied by guest-owned active CPU seconds.""" - - last_window_end: datetime - """Latest raw window_end represented by this row.""" - - latest_meter_emitted_at: Optional[datetime] = None - """Latest meter emission timestamp for linked org buckets, when emitted.""" - - machine_id: str - """Machine identifier.""" - - memory_mib_seconds: int - """Requested memory MiB multiplied by running allocation seconds.""" - - org_metering_bucket_ids: Optional[List[str]] = None - """Org compute bucket IDs this 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.""" - - window_count: int - """Raw metering events compacted into this row.""" diff --git a/src/dedalus_sdk/types/machine_create_params.py b/src/dedalus_sdk/types/machine_create_params.py index 9f724f5..9b80971 100644 --- a/src/dedalus_sdk/types/machine_create_params.py +++ b/src/dedalus_sdk/types/machine_create_params.py @@ -2,9 +2,7 @@ from __future__ import annotations -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo +from typing_extensions import TypedDict __all__ = ["MachineCreateParams"] @@ -21,5 +19,3 @@ class MachineCreateParams(TypedDict, total=False): vcpu: float """CPU in vCPUs.""" - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machine_list_params.py b/src/dedalus_sdk/types/machine_list_params.py index a17dbbc..963d7ff 100644 --- a/src/dedalus_sdk/types/machine_list_params.py +++ b/src/dedalus_sdk/types/machine_list_params.py @@ -2,9 +2,7 @@ from __future__ import annotations -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo +from typing_extensions import TypedDict __all__ = ["MachineListParams"] @@ -13,5 +11,3 @@ class MachineListParams(TypedDict, total=False): limit: int cursor: str - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machine_storage_usage.py b/src/dedalus_sdk/types/machine_storage_usage.py deleted file mode 100644 index 5e26335..0000000 --- a/src/dedalus_sdk/types/machine_storage_usage.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import List, Optional -from datetime import datetime - -from .._models import BaseModel - -from .machine_storage_usage_row import MachineStorageUsageRow - -__all__ = ["MachineStorageUsage"] - - -class MachineStorageUsage(BaseModel): - period_end: datetime - """Exclusive usage period end.""" - - period_start: datetime - """Inclusive usage period start.""" - - rows: Optional[List[MachineStorageUsageRow]] = None - """Machine-level storage usage breakdown rows.""" diff --git a/src/dedalus_sdk/types/machine_storage_usage_row.py b/src/dedalus_sdk/types/machine_storage_usage_row.py deleted file mode 100644 index c69ee09..0000000 --- a/src/dedalus_sdk/types/machine_storage_usage_row.py +++ /dev/null @@ -1,31 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Optional -from datetime import datetime - -from .._models import BaseModel - -__all__ = ["MachineStorageUsageRow"] - - -class MachineStorageUsageRow(BaseModel): - bucket_end: datetime - """Exclusive usage bucket end.""" - - bucket_start: datetime - """Inclusive usage bucket start.""" - - latest_meter_emitted_at: Optional[datetime] = None - """Latest meter emission timestamp for the linked org bucket, when emitted.""" - - 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 row contributes to.""" - - storage_mib_seconds: int - """Allocated logical MiB-seconds for this machine.""" diff --git a/src/dedalus_sdk/types/machine_update_params.py b/src/dedalus_sdk/types/machine_update_params.py index 3a5abd3..c655af9 100644 --- a/src/dedalus_sdk/types/machine_update_params.py +++ b/src/dedalus_sdk/types/machine_update_params.py @@ -2,15 +2,14 @@ from __future__ import annotations -from typing_extensions import Annotated, Required, TypedDict - -from .._utils import PropertyInfo +from typing_extensions import Required, TypedDict __all__ = ["MachineUpdateParams"] class MachineUpdateParams(TypedDict, total=False): machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" autosleep: str """Idle window before autosleep. Accepts fixed duration units like 30s, 30m, 2h, 7d3h4s, or 1w3d, raw seconds ("1800"), or never to disable.""" @@ -23,5 +22,3 @@ class MachineUpdateParams(TypedDict, total=False): vcpu: float """CPU in vCPUs.""" - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/__init__.py b/src/dedalus_sdk/types/machines/__init__.py index f4d1a71..dbe964f 100644 --- a/src/dedalus_sdk/types/machines/__init__.py +++ b/src/dedalus_sdk/types/machines/__init__.py @@ -2,40 +2,21 @@ from __future__ import annotations -from .artifact_list import ArtifactList as ArtifactList from .artifact_ref import ArtifactRef as ArtifactRef -from .artifact import Artifact as Artifact from .execution_event import ExecutionEvent as ExecutionEvent from .execution_events import ExecutionEvents as ExecutionEvents from .execution_list import ExecutionList as ExecutionList from .execution_output import ExecutionOutput as ExecutionOutput from .execution import Execution as Execution -from .machine_network import MachineNetwork as MachineNetwork -from .port_list import PortList as PortList -from .port import Port as Port from .ssh_connection import SSHConnection as SSHConnection from .ssh_host_trust import SSHHostTrust as SSHHostTrust from .ssh_session_list import SSHSessionList as SSHSessionList from .ssh_session import SSHSession as SSHSession -from .terminal_client_event import TerminalClientEvent as TerminalClientEvent -from .terminal_closed_event import TerminalClosedEvent as TerminalClosedEvent -from .terminal_error_event import TerminalErrorEvent as TerminalErrorEvent -from .terminal_input_event import TerminalInputEvent as TerminalInputEvent -from .terminal_list import TerminalList as TerminalList -from .terminal_output_event import TerminalOutputEvent as TerminalOutputEvent -from .terminal_resize_event import TerminalResizeEvent as TerminalResizeEvent -from .terminal import Terminal as Terminal -from .terminal_server_event import TerminalServerEvent as TerminalServerEvent -from .artifact_list_params import ArtifactListParams as ArtifactListParams -from .port_list_params import PortListParams as PortListParams -from .port_create_params import PortCreateParams as PortCreateParams from .ssh_list_params import SSHListParams as SSHListParams from .ssh_create_params import SSHCreateParams as SSHCreateParams from .execution_list_params import ExecutionListParams as ExecutionListParams from .execution_create_params import ExecutionCreateParams as ExecutionCreateParams from .execution_events_params import ExecutionEventsParams as ExecutionEventsParams -from .terminal_list_params import TerminalListParams as TerminalListParams -from .terminal_create_params import TerminalCreateParams as TerminalCreateParams -from .terminal_input_event_param import TerminalInputEventParam as TerminalInputEventParam -from .terminal_resize_event_param import TerminalResizeEventParam as TerminalResizeEventParam -from .terminal_client_event_param import TerminalClientEventParam as TerminalClientEventParam +from .connect_client_event import ConnectClientEvent as ConnectClientEvent +from .connect_client_event_param import ConnectClientEventParam as ConnectClientEventParam +from .connect_server_event import ConnectServerEvent as ConnectServerEvent diff --git a/src/dedalus_sdk/types/machines/artifact.py b/src/dedalus_sdk/types/machines/artifact.py deleted file mode 100644 index 7d5fa86..0000000 --- a/src/dedalus_sdk/types/machines/artifact.py +++ /dev/null @@ -1,30 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Optional -from datetime import datetime - -from ..._models import BaseModel - -__all__ = ["Artifact"] - - -class Artifact(BaseModel): - artifact_id: str - - created_at: datetime - - download_url: Optional[str] = None - - execution_id: Optional[str] = None - - expires_at: Optional[datetime] = None - - machine_id: str - - mime_type: Optional[str] = None - - name: str - - sha256: Optional[str] = None - - size_bytes: int diff --git a/src/dedalus_sdk/types/machines/artifact_list.py b/src/dedalus_sdk/types/machines/artifact_list.py deleted file mode 100644 index 1bd78df..0000000 --- a/src/dedalus_sdk/types/machines/artifact_list.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import List, Optional - -from ..._models import BaseModel - -from .artifact import Artifact - -__all__ = ["ArtifactList"] - - -class ArtifactList(BaseModel): - items: Optional[List[Artifact]] = None - - next_cursor: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/artifact_list_params.py b/src/dedalus_sdk/types/machines/artifact_list_params.py deleted file mode 100644 index c53be52..0000000 --- a/src/dedalus_sdk/types/machines/artifact_list_params.py +++ /dev/null @@ -1,19 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["ArtifactListParams"] - - -class ArtifactListParams(TypedDict, total=False): - machine_id: Required[str] - - limit: int - - cursor: str - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/connect_client_event.py b/src/dedalus_sdk/types/machines/connect_client_event.py new file mode 100644 index 0000000..7470d04 --- /dev/null +++ b/src/dedalus_sdk/types/machines/connect_client_event.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import TypeAlias + +from ..._models import BaseModel + +__all__ = ["ConnectClientEvent", "WebSocketEvent"] + + +class WebSocketEvent(BaseModel): + pass + + +ConnectClientEvent: TypeAlias = WebSocketEvent diff --git a/src/dedalus_sdk/types/machines/connect_client_event_param.py b/src/dedalus_sdk/types/machines/connect_client_event_param.py new file mode 100644 index 0000000..1e5f97c --- /dev/null +++ b/src/dedalus_sdk/types/machines/connect_client_event_param.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import TypeAlias, TypedDict + +__all__ = ["ConnectClientEventParam", "WebSocketEvent"] + + +class WebSocketEvent(TypedDict, total=False): + pass + + +ConnectClientEventParam: TypeAlias = Union[WebSocketEvent] diff --git a/src/dedalus_sdk/types/machines/connect_server_event.py b/src/dedalus_sdk/types/machines/connect_server_event.py new file mode 100644 index 0000000..7934662 --- /dev/null +++ b/src/dedalus_sdk/types/machines/connect_server_event.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import TypeAlias + +from ..._models import BaseModel + +__all__ = ["ConnectServerEvent", "WebSocketEvent"] + + +class WebSocketEvent(BaseModel): + pass + + +ConnectServerEvent: TypeAlias = WebSocketEvent diff --git a/src/dedalus_sdk/types/machines/execution.py b/src/dedalus_sdk/types/machines/execution.py index b08f14b..4420b89 100644 --- a/src/dedalus_sdk/types/machines/execution.py +++ b/src/dedalus_sdk/types/machines/execution.py @@ -8,7 +8,17 @@ from .artifact_ref import ArtifactRef -__all__ = ["Execution"] +__all__ = ["Execution", "LogCapture"] + + +class LogCapture(BaseModel): + code: Optional[str] = None + + lost_bytes: Optional[str] = None + + state: Optional[Literal["pending", "incomplete", "unavailable"]] = None + + unconfirmed_bytes: Optional[str] = None class Execution(BaseModel): @@ -20,6 +30,10 @@ class Execution(BaseModel): created_at: datetime + creation_request_id: Optional[str] = None + + creation_trace_id: Optional[str] = None + cwd: Optional[str] = None env_keys: Optional[List[str]] = None @@ -34,6 +48,8 @@ class Execution(BaseModel): expires_at: Optional[datetime] = None + log_capture: LogCapture + machine_id: str retry_after_ms: Optional[int] = None diff --git a/src/dedalus_sdk/types/machines/execution_create_params.py b/src/dedalus_sdk/types/machines/execution_create_params.py index 55c67ed..ca4a4f0 100644 --- a/src/dedalus_sdk/types/machines/execution_create_params.py +++ b/src/dedalus_sdk/types/machines/execution_create_params.py @@ -3,16 +3,15 @@ from __future__ import annotations from typing import Dict, Optional -from typing_extensions import Annotated, Required, TypedDict +from typing_extensions import Required, TypedDict from ..._types import SequenceNotStr -from ..._utils import PropertyInfo - __all__ = ["ExecutionCreateParams"] class ExecutionCreateParams(TypedDict, total=False): machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" command: Required[Optional[SequenceNotStr[str]]] @@ -23,5 +22,3 @@ class ExecutionCreateParams(TypedDict, total=False): stdin: str timeout_ms: int - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/execution_events_params.py b/src/dedalus_sdk/types/machines/execution_events_params.py index 2dc6e7d..abe98ca 100644 --- a/src/dedalus_sdk/types/machines/execution_events_params.py +++ b/src/dedalus_sdk/types/machines/execution_events_params.py @@ -2,20 +2,17 @@ from __future__ import annotations -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo +from typing_extensions import Required, TypedDict __all__ = ["ExecutionEventsParams"] class ExecutionEventsParams(TypedDict, total=False): machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" execution_id: Required[str] limit: int cursor: str - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/execution_list_params.py b/src/dedalus_sdk/types/machines/execution_list_params.py index 264839b..7781858 100644 --- a/src/dedalus_sdk/types/machines/execution_list_params.py +++ b/src/dedalus_sdk/types/machines/execution_list_params.py @@ -2,18 +2,15 @@ from __future__ import annotations -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo +from typing_extensions import Required, TypedDict __all__ = ["ExecutionListParams"] class ExecutionListParams(TypedDict, total=False): machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" limit: int cursor: str - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/machine_network.py b/src/dedalus_sdk/types/machines/machine_network.py deleted file mode 100644 index 0b4b434..0000000 --- a/src/dedalus_sdk/types/machines/machine_network.py +++ /dev/null @@ -1,19 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from ..._models import BaseModel - -__all__ = ["MachineNetwork"] - - -class MachineNetwork(BaseModel): - hostname: str - - machine_id: str - - network_id: str - - network_name: str - - private_ipv4: str - - private_ipv6: str diff --git a/src/dedalus_sdk/types/machines/port.py b/src/dedalus_sdk/types/machines/port.py deleted file mode 100644 index 909b745..0000000 --- a/src/dedalus_sdk/types/machines/port.py +++ /dev/null @@ -1,35 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["Port"] - - -class Port(BaseModel): - created_at: datetime - - error_code: Optional[str] = None - - error_message: Optional[str] = None - - expires_at: Optional[datetime] = None - - machine_id: str - - port: int - - port_id: str - - protocol: Optional[Literal["http", "https"]] = None - - ready_at: Optional[datetime] = None - - retry_after_ms: Optional[int] = None - - status: Literal["wake_in_progress", "ready", "closed", "expired", "failed"] - - url: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/port_create_params.py b/src/dedalus_sdk/types/machines/port_create_params.py deleted file mode 100644 index c5ac5d2..0000000 --- a/src/dedalus_sdk/types/machines/port_create_params.py +++ /dev/null @@ -1,19 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, Literal, Required, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["PortCreateParams"] - - -class PortCreateParams(TypedDict, total=False): - machine_id: Required[str] - - port: Required[int] - - protocol: Literal["http", "https"] - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/port_list.py b/src/dedalus_sdk/types/machines/port_list.py deleted file mode 100644 index 7fc5b82..0000000 --- a/src/dedalus_sdk/types/machines/port_list.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import List, Optional - -from ..._models import BaseModel - -from .port import Port - -__all__ = ["PortList"] - - -class PortList(BaseModel): - items: Optional[List[Port]] = None - - next_cursor: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/port_list_params.py b/src/dedalus_sdk/types/machines/port_list_params.py deleted file mode 100644 index 60b8de0..0000000 --- a/src/dedalus_sdk/types/machines/port_list_params.py +++ /dev/null @@ -1,19 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["PortListParams"] - - -class PortListParams(TypedDict, total=False): - machine_id: Required[str] - - limit: int - - cursor: str - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/ssh_create_params.py b/src/dedalus_sdk/types/machines/ssh_create_params.py index 46cebf0..ea2ef29 100644 --- a/src/dedalus_sdk/types/machines/ssh_create_params.py +++ b/src/dedalus_sdk/types/machines/ssh_create_params.py @@ -2,16 +2,13 @@ from __future__ import annotations -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo +from typing_extensions import Required, TypedDict __all__ = ["SSHCreateParams"] class SSHCreateParams(TypedDict, total=False): machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" public_key: Required[str] - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/ssh_list_params.py b/src/dedalus_sdk/types/machines/ssh_list_params.py index a3f4bd5..ff18d26 100644 --- a/src/dedalus_sdk/types/machines/ssh_list_params.py +++ b/src/dedalus_sdk/types/machines/ssh_list_params.py @@ -2,18 +2,15 @@ from __future__ import annotations -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo +from typing_extensions import Required, TypedDict __all__ = ["SSHListParams"] class SSHListParams(TypedDict, total=False): machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" limit: int cursor: str - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/ssh_session.py b/src/dedalus_sdk/types/machines/ssh_session.py index 7eacfd3..3094f5b 100644 --- a/src/dedalus_sdk/types/machines/ssh_session.py +++ b/src/dedalus_sdk/types/machines/ssh_session.py @@ -30,4 +30,4 @@ class SSHSession(BaseModel): session_id: str - status: Literal["wake_in_progress", "ready", "closed", "expired", "failed"] + status: Literal["wake_in_progress", "ssh_in_progress", "ready", "closed", "expired", "failed"] diff --git a/src/dedalus_sdk/types/machines/terminal.py b/src/dedalus_sdk/types/machines/terminal.py deleted file mode 100644 index c86ceb9..0000000 --- a/src/dedalus_sdk/types/machines/terminal.py +++ /dev/null @@ -1,37 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["Terminal"] - - -class Terminal(BaseModel): - created_at: datetime - - error_code: Optional[str] = None - - error_message: Optional[str] = None - - expires_at: Optional[datetime] = None - - height: int - - machine_id: str - - protocol: Optional[Literal["websocket"]] = None - - ready_at: Optional[datetime] = None - - retry_after_ms: Optional[int] = None - - status: Literal["wake_in_progress", "ready", "closed", "expired", "failed"] - - stream_url: Optional[str] = None - - terminal_id: str - - width: int diff --git a/src/dedalus_sdk/types/machines/terminal_client_event.py b/src/dedalus_sdk/types/machines/terminal_client_event.py deleted file mode 100644 index 52c775c..0000000 --- a/src/dedalus_sdk/types/machines/terminal_client_event.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Union -from typing_extensions import Annotated, TypeAlias - -from ..._utils import PropertyInfo - -from .terminal_input_event import TerminalInputEvent -from .terminal_resize_event import TerminalResizeEvent - -__all__ = ["TerminalClientEvent"] - -TerminalClientEvent: TypeAlias = Annotated[ - Union[TerminalInputEvent, TerminalResizeEvent], PropertyInfo(discriminator="type") -] diff --git a/src/dedalus_sdk/types/machines/terminal_client_event_param.py b/src/dedalus_sdk/types/machines/terminal_client_event_param.py deleted file mode 100644 index 65c9640..0000000 --- a/src/dedalus_sdk/types/machines/terminal_client_event_param.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing import Union -from typing_extensions import TypeAlias - -from .terminal_input_event_param import TerminalInputEventParam -from .terminal_resize_event_param import TerminalResizeEventParam - -__all__ = ["TerminalClientEventParam"] - - -TerminalClientEventParam: TypeAlias = Union[TerminalInputEventParam, TerminalResizeEventParam] diff --git a/src/dedalus_sdk/types/machines/terminal_closed_event.py b/src/dedalus_sdk/types/machines/terminal_closed_event.py deleted file mode 100644 index 4d576dd..0000000 --- a/src/dedalus_sdk/types/machines/terminal_closed_event.py +++ /dev/null @@ -1,11 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["TerminalClosedEvent"] - - -class TerminalClosedEvent(BaseModel): - type: Literal["closed"] diff --git a/src/dedalus_sdk/types/machines/terminal_create_params.py b/src/dedalus_sdk/types/machines/terminal_create_params.py deleted file mode 100644 index f547002..0000000 --- a/src/dedalus_sdk/types/machines/terminal_create_params.py +++ /dev/null @@ -1,26 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing import Dict -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["TerminalCreateParams"] - - -class TerminalCreateParams(TypedDict, total=False): - machine_id: Required[str] - - cwd: str - - env: Dict[str, str] - - height: Required[int] - - shell: str - - width: Required[int] - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/terminal_error_event.py b/src/dedalus_sdk/types/machines/terminal_error_event.py deleted file mode 100644 index f455864..0000000 --- a/src/dedalus_sdk/types/machines/terminal_error_event.py +++ /dev/null @@ -1,16 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["TerminalErrorEvent"] - - -class TerminalErrorEvent(BaseModel): - error_code: Optional[str] = None - - error_message: Optional[str] = None - - type: Literal["error"] diff --git a/src/dedalus_sdk/types/machines/terminal_input_event.py b/src/dedalus_sdk/types/machines/terminal_input_event.py deleted file mode 100644 index 0cd1a3b..0000000 --- a/src/dedalus_sdk/types/machines/terminal_input_event.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["TerminalInputEvent"] - - -class TerminalInputEvent(BaseModel): - data: str - """Base64-encoded terminal input.""" - - type: Literal["input"] diff --git a/src/dedalus_sdk/types/machines/terminal_input_event_param.py b/src/dedalus_sdk/types/machines/terminal_input_event_param.py deleted file mode 100644 index b518482..0000000 --- a/src/dedalus_sdk/types/machines/terminal_input_event_param.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing import Union -from typing_extensions import Annotated, Literal, Required, TypedDict -from ..._types import Base64FileInput - -from ..._utils import PropertyInfo - -__all__ = ["TerminalInputEventParam"] - - -class TerminalInputEventParam(TypedDict, total=False): - data: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")]] - """Base64-encoded terminal input.""" - - type: Required[Literal["input"]] diff --git a/src/dedalus_sdk/types/machines/terminal_list.py b/src/dedalus_sdk/types/machines/terminal_list.py deleted file mode 100644 index ab117b2..0000000 --- a/src/dedalus_sdk/types/machines/terminal_list.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import List, Optional - -from ..._models import BaseModel - -from .terminal import Terminal - -__all__ = ["TerminalList"] - - -class TerminalList(BaseModel): - items: Optional[List[Terminal]] = None - - next_cursor: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/terminal_list_params.py b/src/dedalus_sdk/types/machines/terminal_list_params.py deleted file mode 100644 index d5aa311..0000000 --- a/src/dedalus_sdk/types/machines/terminal_list_params.py +++ /dev/null @@ -1,19 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, Required, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["TerminalListParams"] - - -class TerminalListParams(TypedDict, total=False): - machine_id: Required[str] - - limit: int - - cursor: str - - x_dedalus_org_id: Annotated[str, PropertyInfo(alias="X-Dedalus-Org-Id")] diff --git a/src/dedalus_sdk/types/machines/terminal_output_event.py b/src/dedalus_sdk/types/machines/terminal_output_event.py deleted file mode 100644 index cc0395f..0000000 --- a/src/dedalus_sdk/types/machines/terminal_output_event.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["TerminalOutputEvent"] - - -class TerminalOutputEvent(BaseModel): - data: str - """Base64-encoded terminal output.""" - - type: Literal["output"] diff --git a/src/dedalus_sdk/types/machines/terminal_resize_event.py b/src/dedalus_sdk/types/machines/terminal_resize_event.py deleted file mode 100644 index f6ba3a1..0000000 --- a/src/dedalus_sdk/types/machines/terminal_resize_event.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["TerminalResizeEvent"] - - -class TerminalResizeEvent(BaseModel): - height: int - - type: Literal["resize"] - - width: int diff --git a/src/dedalus_sdk/types/machines/terminal_resize_event_param.py b/src/dedalus_sdk/types/machines/terminal_resize_event_param.py deleted file mode 100644 index 7500ae5..0000000 --- a/src/dedalus_sdk/types/machines/terminal_resize_event_param.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["TerminalResizeEventParam"] - - -class TerminalResizeEventParam(TypedDict, total=False): - height: Required[int] - - type: Required[Literal["resize"]] - - width: Required[int] diff --git a/src/dedalus_sdk/types/machines/terminal_server_event.py b/src/dedalus_sdk/types/machines/terminal_server_event.py deleted file mode 100644 index b16a55c..0000000 --- a/src/dedalus_sdk/types/machines/terminal_server_event.py +++ /dev/null @@ -1,16 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Union -from typing_extensions import Annotated, TypeAlias - -from ..._utils import PropertyInfo - -from .terminal_output_event import TerminalOutputEvent -from .terminal_error_event import TerminalErrorEvent -from .terminal_closed_event import TerminalClosedEvent - -__all__ = ["TerminalServerEvent"] - -TerminalServerEvent: TypeAlias = Annotated[ - Union[TerminalOutputEvent, TerminalErrorEvent, TerminalClosedEvent], PropertyInfo(discriminator="type") -] diff --git a/src/dedalus_sdk/types/network.py b/src/dedalus_sdk/types/network.py deleted file mode 100644 index c087fdf..0000000 --- a/src/dedalus_sdk/types/network.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import List, Optional - -from .._models import BaseModel - -from .network_gateway import NetworkGateway - -__all__ = ["Network"] - - -class Network(BaseModel): - gateways: Optional[List[NetworkGateway]] = None - - name: str - - network_id: str diff --git a/src/dedalus_sdk/types/network_gateway.py b/src/dedalus_sdk/types/network_gateway.py deleted file mode 100644 index 3bda536..0000000 --- a/src/dedalus_sdk/types/network_gateway.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from typing import Optional -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = ["NetworkGateway"] - - -class NetworkGateway(BaseModel): - hostname: str - - kind: Literal["ssh", "port"] - - port: Optional[int] = None - - protocol: Literal["ssh", "https"] diff --git a/src/dedalus_sdk/types/org_usage.py b/src/dedalus_sdk/types/org_usage.py deleted file mode 100644 index c4381d1..0000000 --- a/src/dedalus_sdk/types/org_usage.py +++ /dev/null @@ -1,28 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.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 guest-owned active CPU seconds for the period.""" - - billed_logical_storage_mib_seconds: int - """Closed billable logical MiB-seconds for the period.""" - - billed_memory_mib_seconds: int - """Closed requested memory MiB multiplied by running allocation 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/usage_machine_compute_params.py b/src/dedalus_sdk/types/usage_machine_compute_params.py deleted file mode 100644 index f1c8a61..0000000 --- a/src/dedalus_sdk/types/usage_machine_compute_params.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["UsageMachineComputeParams"] - - -class UsageMachineComputeParams(TypedDict, total=False): - period_start: str - """Usage period start (YYYY-MM-DD). Defaults to first of current month.""" - - period_end: str - """Last UTC usage date to include (YYYY-MM-DD). Defaults to current time.""" - - machine_id: str - """Optional machine ID filter.""" - - granularity: str - """Usage breakdown granularity: hour or day. Defaults to hour.""" diff --git a/src/dedalus_sdk/types/usage_machine_storage_params.py b/src/dedalus_sdk/types/usage_machine_storage_params.py deleted file mode 100644 index 230ac44..0000000 --- a/src/dedalus_sdk/types/usage_machine_storage_params.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["UsageMachineStorageParams"] - - -class UsageMachineStorageParams(TypedDict, total=False): - period_start: str - """Usage period start (YYYY-MM-DD). Defaults to first of current month.""" - - period_end: str - """Last UTC usage date to include (YYYY-MM-DD). Defaults to current time.""" - - machine_id: str - """Optional machine ID filter.""" diff --git a/src/dedalus_sdk/types/usage_retrieve_params.py b/src/dedalus_sdk/types/usage_retrieve_params.py deleted file mode 100644 index e85d9a9..0000000 --- a/src/dedalus_sdk/types/usage_retrieve_params.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["UsageRetrieveParams"] - - -class UsageRetrieveParams(TypedDict, total=False): - period_start: str - """Billing period start (YYYY-MM-DD). Defaults to first of current month.""" diff --git a/tests/smoke-test.py b/tests/smoke-test.py index 459e956..92c5fa3 100644 --- a/tests/smoke-test.py +++ b/tests/smoke-test.py @@ -50,476 +50,145 @@ def _smoke_case_0() -> None: def _smoke_case_1() -> None: - page = client.machines.list( - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_2() -> None: - machine = client.machines.create( - autosleep="300s", - memory_mib=4096, - storage_gib=10, - vcpu=1, - idempotency_key="", - ) - - -def _smoke_case_3() -> None: machine = client.machines.create( autosleep="300s", memory_mib=4096, storage_gib=10, vcpu=1, - x_dedalus_org_id="x_dedalus_org_id", idempotency_key="", ) -def _smoke_case_4() -> None: - machine = client.machines.retrieve( - machine_id="machineID", - ) - - -def _smoke_case_5() -> None: +def _smoke_case_2() -> None: machine = client.machines.retrieve( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) -def _smoke_case_6() -> None: +def _smoke_case_3() -> None: machine = client.machines.update( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) -def _smoke_case_7() -> None: +def _smoke_case_4() -> None: machine = client.machines.update( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", autosleep="", memory_mib=0, storage_gib=0, vcpu=0, - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_8() -> None: - machine = client.machines.delete( - machine_id="machineID", idempotency_key="", ) -def _smoke_case_9() -> None: +def _smoke_case_5() -> None: machine = client.machines.delete( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_10() -> None: - stream = client.machines.watch( - machine_id="machineID", - ) - - for machine in stream: - print(machine) - - -def _smoke_case_11() -> None: - stream = client.machines.watch( - machine_id="machineID", - x_dedalus_org_id="7c9e6679-7425-40de-944b-e07fc1f90ae7", - last_event_id="last_event_id", - ) - - for machine in stream: - print(machine) - - -def _smoke_case_12() -> None: - machine = client.machines.sleep( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) -def _smoke_case_13() -> None: +def _smoke_case_6() -> None: machine = client.machines.sleep( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_14() -> None: - machine = client.machines.wake( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) -def _smoke_case_15() -> None: +def _smoke_case_7() -> None: machine = client.machines.wake( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_16() -> None: - network = client.machines.network.retrieve( - machine_id="machineID", - ) - - -def _smoke_case_17() -> None: - network = client.machines.network.retrieve( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_18() -> None: - page = client.machines.artifacts.list( - machine_id="machineID", - ) - - -def _smoke_case_19() -> None: - page = client.machines.artifacts.list( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_20() -> None: - artifact = client.machines.artifacts.retrieve( - machine_id="machineID", - artifact_id="artifactID", - ) - - -def _smoke_case_21() -> None: - artifact = client.machines.artifacts.retrieve( - machine_id="machineID", - artifact_id="artifactID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_22() -> None: - artifact = client.machines.artifacts.delete( - machine_id="machineID", - artifact_id="artifactID", - idempotency_key="", - ) - - -def _smoke_case_23() -> None: - artifact = client.machines.artifacts.delete( - machine_id="machineID", - artifact_id="artifactID", - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_24() -> None: - page = client.machines.ports.list( - machine_id="machineID", - ) - - -def _smoke_case_25() -> None: - page = client.machines.ports.list( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_26() -> None: - port = client.machines.ports.create( - machine_id="machineID", - port=0, - idempotency_key="", - ) - - -def _smoke_case_27() -> None: - port = client.machines.ports.create( - machine_id="machineID", - port=0, - protocol="http", - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_28() -> None: - port = client.machines.ports.retrieve( - machine_id="machineID", - port_id="portID", - ) - - -def _smoke_case_29() -> None: - port = client.machines.ports.retrieve( - machine_id="machineID", - port_id="portID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_30() -> None: - port = client.machines.ports.delete( - machine_id="machineID", - port_id="portID", - idempotency_key="", - ) - - -def _smoke_case_31() -> None: - port = client.machines.ports.delete( - machine_id="machineID", - port_id="portID", - x_dedalus_org_id="x_dedalus_org_id", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", idempotency_key="", ) -def _smoke_case_32() -> None: - page = client.machines.ssh.list( - machine_id="machineID", - ) - - -def _smoke_case_33() -> None: +def _smoke_case_8() -> None: page = client.machines.ssh.list( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_34() -> None: - ssh = client.machines.ssh.create( - machine_id="machineID", - public_key="", - idempotency_key="", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) -def _smoke_case_35() -> None: +def _smoke_case_9() -> None: ssh = client.machines.ssh.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", public_key="", - x_dedalus_org_id="x_dedalus_org_id", idempotency_key="", ) -def _smoke_case_36() -> None: - ssh = client.machines.ssh.retrieve( - machine_id="machineID", - session_id="sessionID", - ) - - -def _smoke_case_37() -> None: +def _smoke_case_10() -> None: ssh = client.machines.ssh.retrieve( - machine_id="machineID", - session_id="sessionID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_38() -> None: - ssh = client.machines.ssh.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", - idempotency_key="", ) -def _smoke_case_39() -> None: +def _smoke_case_11() -> None: ssh = client.machines.ssh.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", - x_dedalus_org_id="x_dedalus_org_id", idempotency_key="", ) -def _smoke_case_40() -> None: - page = client.machines.executions.list( - machine_id="machineID", - ) - - -def _smoke_case_41() -> None: +def _smoke_case_12() -> None: page = client.machines.executions.list( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) -def _smoke_case_42() -> None: +def _smoke_case_13() -> None: execution = client.machines.executions.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", command=[""], idempotency_key="", ) -def _smoke_case_43() -> None: +def _smoke_case_14() -> None: execution = client.machines.executions.create( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", command=[""], cwd="", env={}, stdin="", timeout_ms=0, - x_dedalus_org_id="x_dedalus_org_id", idempotency_key="", ) -def _smoke_case_44() -> None: - execution = client.machines.executions.retrieve( - machine_id="machineID", - execution_id="executionID", - ) - - -def _smoke_case_45() -> None: +def _smoke_case_15() -> None: execution = client.machines.executions.retrieve( - machine_id="machineID", - execution_id="executionID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_46() -> None: - execution = client.machines.executions.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", - idempotency_key="", ) -def _smoke_case_47() -> None: +def _smoke_case_16() -> None: execution = client.machines.executions.delete( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", - x_dedalus_org_id="x_dedalus_org_id", idempotency_key="", ) -def _smoke_case_48() -> None: - execution = client.machines.executions.output( - machine_id="machineID", - execution_id="executionID", - ) - - -def _smoke_case_49() -> None: +def _smoke_case_17() -> None: execution = client.machines.executions.output( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", - x_dedalus_org_id="x_dedalus_org_id", ) -def _smoke_case_50() -> None: - page = client.machines.executions.events( - machine_id="machineID", - execution_id="executionID", - ) - - -def _smoke_case_51() -> None: +def _smoke_case_18() -> None: page = client.machines.executions.events( - machine_id="machineID", + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_52() -> None: - page = client.machines.terminals.list( - machine_id="machineID", - ) - - -def _smoke_case_53() -> None: - page = client.machines.terminals.list( - machine_id="machineID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_54() -> None: - terminal = client.machines.terminals.create( - machine_id="machineID", - height=0, - width=0, - idempotency_key="", - ) - - -def _smoke_case_55() -> None: - terminal = client.machines.terminals.create( - machine_id="machineID", - cwd="", - env={}, - height=0, - shell="", - width=0, - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_56() -> None: - terminal = client.machines.terminals.retrieve( - machine_id="machineID", - terminal_id="terminalID", - ) - - -def _smoke_case_57() -> None: - terminal = client.machines.terminals.retrieve( - machine_id="machineID", - terminal_id="terminalID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_58() -> None: - terminal = client.machines.terminals.delete( - machine_id="machineID", - terminal_id="terminalID", - idempotency_key="", ) -def _smoke_case_59() -> None: - terminal = client.machines.terminals.delete( - machine_id="machineID", - terminal_id="terminalID", - x_dedalus_org_id="x_dedalus_org_id", - idempotency_key="", - ) - - -def _smoke_case_60() -> None: +def _smoke_case_19() -> None: def _probe() -> None: with client.machines.terminals.connect( machine_id="machineID", @@ -533,536 +202,130 @@ def _probe() -> None: _probe() -def _smoke_case_61() -> None: - network = client.networks.retrieve( - network_id="networkID", - ) - - -def _smoke_case_62() -> None: - network = client.networks.retrieve( - network_id="networkID", - x_dedalus_org_id="x_dedalus_org_id", - ) - - -def _smoke_case_63() -> None: - usage = client.usage.retrieve() - - -def _smoke_case_64() -> None: - usage = client.usage.retrieve( - period_start="period_start", - ) - - -def _smoke_case_65() -> None: - usage = client.usage.machine_compute() - - -def _smoke_case_66() -> None: - usage = client.usage.machine_compute( - period_start="period_start", - period_end="period_end", - machine_id="machine_id", - granularity="granularity", - ) - - -def _smoke_case_67() -> None: - usage = client.usage.machine_storage() - - -def _smoke_case_68() -> None: - usage = client.usage.machine_storage( - period_start="period_start", - period_end="period_end", - machine_id="machine_id", - ) - - cases: list[SmokeCase] = [ { "operation": "list", "method": "GET", "path": "/v1/machines", - "label": "required params", "run": _smoke_case_0, }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines", - "label": "all params", - "run": _smoke_case_1, - }, - { - "operation": "create", - "method": "POST", - "path": "/v1/machines", - "label": "required params", - "run": _smoke_case_2, - }, { "operation": "create", "method": "POST", "path": "/v1/machines", - "label": "all params", - "run": _smoke_case_3, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}", - "label": "required params", - "run": _smoke_case_4, + "run": _smoke_case_1, }, { "operation": "retrieve", "method": "GET", "path": "/v1/machines/{machine_id}", - "label": "all params", - "run": _smoke_case_5, + "run": _smoke_case_2, }, { "operation": "update", "method": "PATCH", "path": "/v1/machines/{machine_id}", "label": "required params", - "run": _smoke_case_6, + "run": _smoke_case_3, }, { "operation": "update", "method": "PATCH", "path": "/v1/machines/{machine_id}", "label": "all params", - "run": _smoke_case_7, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}", - "label": "required params", - "run": _smoke_case_8, + "run": _smoke_case_4, }, { "operation": "delete", "method": "DELETE", "path": "/v1/machines/{machine_id}", - "label": "all params", - "run": _smoke_case_9, - }, - { - "operation": "watch", - "method": "GET", - "path": "/v1/machines/{machine_id}/status/stream", - "label": "required params", - "run": _smoke_case_10, - }, - { - "operation": "watch", - "method": "GET", - "path": "/v1/machines/{machine_id}/status/stream", - "label": "all params", - "run": _smoke_case_11, - }, - { - "operation": "sleep", - "method": "POST", - "path": "/v1/machines/{machine_id}/sleep", - "label": "required params", - "run": _smoke_case_12, + "run": _smoke_case_5, }, { "operation": "sleep", "method": "POST", "path": "/v1/machines/{machine_id}/sleep", - "label": "all params", - "run": _smoke_case_13, - }, - { - "operation": "wake", - "method": "POST", - "path": "/v1/machines/{machine_id}/wake", - "label": "required params", - "run": _smoke_case_14, + "run": _smoke_case_6, }, { "operation": "wake", "method": "POST", "path": "/v1/machines/{machine_id}/wake", - "label": "all params", - "run": _smoke_case_15, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/network", - "label": "required params", - "run": _smoke_case_16, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/network", - "label": "all params", - "run": _smoke_case_17, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/artifacts", - "label": "required params", - "run": _smoke_case_18, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/artifacts", - "label": "all params", - "run": _smoke_case_19, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", - "label": "required params", - "run": _smoke_case_20, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", - "label": "all params", - "run": _smoke_case_21, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", - "label": "required params", - "run": _smoke_case_22, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/artifacts/{artifact_id}", - "label": "all params", - "run": _smoke_case_23, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/ports", - "label": "required params", - "run": _smoke_case_24, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/ports", - "label": "all params", - "run": _smoke_case_25, - }, - { - "operation": "create", - "method": "POST", - "path": "/v1/machines/{machine_id}/ports", - "label": "required params", - "run": _smoke_case_26, - }, - { - "operation": "create", - "method": "POST", - "path": "/v1/machines/{machine_id}/ports", - "label": "all params", - "run": _smoke_case_27, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/ports/{port_id}", - "label": "required params", - "run": _smoke_case_28, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/ports/{port_id}", - "label": "all params", - "run": _smoke_case_29, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/ports/{port_id}", - "label": "required params", - "run": _smoke_case_30, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/ports/{port_id}", - "label": "all params", - "run": _smoke_case_31, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/ssh", - "label": "required params", - "run": _smoke_case_32, + "run": _smoke_case_7, }, { "operation": "list", "method": "GET", "path": "/v1/machines/{machine_id}/ssh", - "label": "all params", - "run": _smoke_case_33, - }, - { - "operation": "create", - "method": "POST", - "path": "/v1/machines/{machine_id}/ssh", - "label": "required params", - "run": _smoke_case_34, + "run": _smoke_case_8, }, { "operation": "create", "method": "POST", "path": "/v1/machines/{machine_id}/ssh", - "label": "all params", - "run": _smoke_case_35, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "label": "required params", - "run": _smoke_case_36, + "run": _smoke_case_9, }, { "operation": "retrieve", "method": "GET", "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "label": "all params", - "run": _smoke_case_37, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "label": "required params", - "run": _smoke_case_38, + "run": _smoke_case_10, }, { "operation": "delete", "method": "DELETE", "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "label": "all params", - "run": _smoke_case_39, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/executions", - "label": "required params", - "run": _smoke_case_40, + "run": _smoke_case_11, }, { "operation": "list", "method": "GET", "path": "/v1/machines/{machine_id}/executions", - "label": "all params", - "run": _smoke_case_41, + "run": _smoke_case_12, }, { "operation": "create", "method": "POST", "path": "/v1/machines/{machine_id}/executions", "label": "required params", - "run": _smoke_case_42, + "run": _smoke_case_13, }, { "operation": "create", "method": "POST", "path": "/v1/machines/{machine_id}/executions", "label": "all params", - "run": _smoke_case_43, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}", - "label": "required params", - "run": _smoke_case_44, + "run": _smoke_case_14, }, { "operation": "retrieve", "method": "GET", "path": "/v1/machines/{machine_id}/executions/{execution_id}", - "label": "all params", - "run": _smoke_case_45, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/executions/{execution_id}", - "label": "required params", - "run": _smoke_case_46, + "run": _smoke_case_15, }, { "operation": "delete", "method": "DELETE", "path": "/v1/machines/{machine_id}/executions/{execution_id}", - "label": "all params", - "run": _smoke_case_47, - }, - { - "operation": "output", - "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", - "label": "required params", - "run": _smoke_case_48, + "run": _smoke_case_16, }, { "operation": "output", "method": "GET", "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", - "label": "all params", - "run": _smoke_case_49, - }, - { - "operation": "events", - "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", - "label": "required params", - "run": _smoke_case_50, + "run": _smoke_case_17, }, { "operation": "events", "method": "GET", "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", - "label": "all params", - "run": _smoke_case_51, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals", - "label": "required params", - "run": _smoke_case_52, - }, - { - "operation": "list", - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals", - "label": "all params", - "run": _smoke_case_53, - }, - { - "operation": "create", - "method": "POST", - "path": "/v1/machines/{machine_id}/terminals", - "label": "required params", - "run": _smoke_case_54, - }, - { - "operation": "create", - "method": "POST", - "path": "/v1/machines/{machine_id}/terminals", - "label": "all params", - "run": _smoke_case_55, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", - "label": "required params", - "run": _smoke_case_56, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", - "label": "all params", - "run": _smoke_case_57, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", - "label": "required params", - "run": _smoke_case_58, - }, - { - "operation": "delete", - "method": "DELETE", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}", - "label": "all params", - "run": _smoke_case_59, + "run": _smoke_case_18, }, { "operation": "connect", "method": "GET", "path": "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", - "run": _smoke_case_60, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/networks/{network_id}", - "label": "required params", - "run": _smoke_case_61, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/networks/{network_id}", - "label": "all params", - "run": _smoke_case_62, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/usage", - "label": "required params", - "run": _smoke_case_63, - }, - { - "operation": "retrieve", - "method": "GET", - "path": "/v1/usage", - "label": "all params", - "run": _smoke_case_64, - }, - { - "operation": "machineCompute", - "method": "GET", - "path": "/v1/usage/machines/compute", - "label": "required params", - "run": _smoke_case_65, - }, - { - "operation": "machineCompute", - "method": "GET", - "path": "/v1/usage/machines/compute", - "label": "all params", - "run": _smoke_case_66, - }, - { - "operation": "machineStorage", - "method": "GET", - "path": "/v1/usage/machines/storage", - "label": "required params", - "run": _smoke_case_67, - }, - { - "operation": "machineStorage", - "method": "GET", - "path": "/v1/usage/machines/storage", - "label": "all params", - "run": _smoke_case_68, + "run": _smoke_case_19, }, ] From 5ad53fdb1238c2bd715ff69459bf663deaa94a78 Mon Sep 17 00:00:00 2001 From: scalarbot Date: Wed, 23 Sep 2026 20:21:18 +0000 Subject: [PATCH 3/6] feat(api)!: remove auth scheme Bearer (+25 more changes) - Removed `bearer` auth scheme `Bearer`. - Added operation `machines.reboot` (`POST /v1/machines/{machine_id}/reboot`). - Added operation `machines.executions.logs.retrieve` (`GET /v1/machines/{machine_id}/executions/{execution_id}/logs`). - Added operation `machines.executions.logs.reauthorize` (`POST /v1/machines/{machine_id}/executions/{execution_id}/logs/reauthorize`). - Added operation `machines.executions.logs.createToken` (`POST /v1/machines/{machine_id}/executions/{execution_id}/logs/token`). - Added operation `machines.autoresizing.retrieve` (`GET /v1/machines/{machine_id}/autoresizing`). - Added operation `machines.autoresizing.update` (`PUT /v1/machines/{machine_id}/autoresizing`). - Added operation `organization.autoresizing.retrieve` (`GET /v1/organization/autoresizing`). - Added operation `organization.autoresizing.update` (`PUT /v1/organization/autoresizing`). - Removed operation `machines.terminals.connect` (`GET /v1/machines/{machine_id}/terminals/{terminal_id}/stream`). - Added schema `status`. - Added schema `policy`. - Added schema `settings`. - Added schema `publication`. - Added schema `read_token`. - Added optional property `RetrieveResponseHeaders.Cache-Control`. - Removed optional property `RetrieveResponseHeaders.ETag`. - Added schema `RebootResponseHeaders`. - Added schema `RebootStatus401ResponseHeaders`. - Added schema `RebootStatus403ResponseHeaders`. - Added schema `RebootStatus409ResponseHeaders`. - Added schema `RebootStatus429ResponseHeaders`. - Added schema `RebootStatus503ResponseHeaders`. - Added schema `RebootStatusdefaultResponseHeaders`. - Added schema `ReauthorizeResponseHeaders`. - Added schema `CreateTokenResponseHeaders`. BREAKING CHANGE: 3 breaking changes to the SDK surface. - Removed `bearer` auth scheme `Bearer`. - Removed operation `machines.terminals.connect` (`GET /v1/machines/{machine_id}/terminals/{terminal_id}/stream`). - Removed optional property `RetrieveResponseHeaders.ETag`. Build: QacznU18hhZgz2eCKq4td --- .claude/skills/dedalus-python-sdk/SKILL.md | 19 +- README.md | 26 +- SKILL.md | 19 +- api.md | 132 +- pyproject.toml | 1 - scalar-sdk.manifest.json | 3618 ++++++++++++----- src/dedalus_sdk/__init__.py | 7 - src/dedalus_sdk/_client.py | 151 +- src/dedalus_sdk/resources/__init__.py | 14 + .../resources/machines/__init__.py | 26 +- .../resources/machines/autoresizing.py | 281 ++ .../resources/machines/executions/__init__.py | 33 + .../machines/{ => executions}/executions.py | 56 +- .../resources/machines/executions/logs.py | 423 ++ .../resources/machines/machines.py | 154 +- .../resources/machines/terminals/__init__.py | 27 - .../resources/machines/terminals/terminals.py | 124 - .../resources/machines/terminals/ws.py | 782 ---- .../resources/organization/__init__.py | 33 + .../resources/organization/autoresizing.py | 259 ++ .../resources/organization/organization.py | 89 + src/dedalus_sdk/types/__init__.py | 6 +- .../types/machine_reboot_params.py | 15 + src/dedalus_sdk/types/machines/__init__.py | 5 +- .../machines/autoresizing_update_params.py | 14 + .../types/machines/connect_client_event.py | 17 - .../machines/connect_client_event_param.py | 15 - .../types/machines/connect_server_event.py | 17 - .../types/machines/executions/__init__.py | 6 + .../types/machines/executions/read_token.py | 21 + .../types/machines/executions/status.py | 40 + src/dedalus_sdk/types/machines/settings.py | 9 + .../types/organization/__init__.py | 6 + .../autoresizing_update_params.py | 12 + src/dedalus_sdk/types/organization/policy.py | 10 + .../types/websocket_connection_options.py | 21 - .../types/websocket_reconnection.py | 36 - tests/smoke-test.py | 169 +- 38 files changed, 4317 insertions(+), 2376 deletions(-) create mode 100644 src/dedalus_sdk/resources/machines/autoresizing.py create mode 100644 src/dedalus_sdk/resources/machines/executions/__init__.py rename src/dedalus_sdk/resources/machines/{ => executions}/executions.py (94%) create mode 100644 src/dedalus_sdk/resources/machines/executions/logs.py delete mode 100644 src/dedalus_sdk/resources/machines/terminals/__init__.py delete mode 100644 src/dedalus_sdk/resources/machines/terminals/terminals.py delete mode 100644 src/dedalus_sdk/resources/machines/terminals/ws.py create mode 100644 src/dedalus_sdk/resources/organization/__init__.py create mode 100644 src/dedalus_sdk/resources/organization/autoresizing.py create mode 100644 src/dedalus_sdk/resources/organization/organization.py create mode 100644 src/dedalus_sdk/types/machine_reboot_params.py create mode 100644 src/dedalus_sdk/types/machines/autoresizing_update_params.py delete mode 100644 src/dedalus_sdk/types/machines/connect_client_event.py delete mode 100644 src/dedalus_sdk/types/machines/connect_client_event_param.py delete mode 100644 src/dedalus_sdk/types/machines/connect_server_event.py create mode 100644 src/dedalus_sdk/types/machines/executions/__init__.py create mode 100644 src/dedalus_sdk/types/machines/executions/read_token.py create mode 100644 src/dedalus_sdk/types/machines/executions/status.py create mode 100644 src/dedalus_sdk/types/machines/settings.py create mode 100644 src/dedalus_sdk/types/organization/__init__.py create mode 100644 src/dedalus_sdk/types/organization/autoresizing_update_params.py create mode 100644 src/dedalus_sdk/types/organization/policy.py delete mode 100644 src/dedalus_sdk/types/websocket_connection_options.py delete mode 100644 src/dedalus_sdk/types/websocket_reconnection.py diff --git a/.claude/skills/dedalus-python-sdk/SKILL.md b/.claude/skills/dedalus-python-sdk/SKILL.md index 7c0959a..fc31a48 100644 --- a/.claude/skills/dedalus-python-sdk/SKILL.md +++ b/.claude/skills/dedalus-python-sdk/SKILL.md @@ -21,15 +21,14 @@ import os from dedalus_sdk import Dedalus client = Dedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), + x_api_key=os.environ.get("DEDALUS_X_API_KEY"), ) ``` Provide credentials using the options below. Environment variables are read automatically when the target runtime supports them: -- `x_api_key` (env: `DEDALUS_X_API_KEY`) — API key authentication using X-API-Key header -- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key or short-lived delegated access token in Authorization: Bearer . -- `api_key` (env: `DEDALUS_API_KEY`) — API key authentication using Bearer token +- `x_api_key` (env: `DEDALUS_X_API_KEY`) — Dedalus API key. Alternative to Bearer token. +- `api_key` (env: `DEDALUS_API_KEY`) — Dedalus API key or short-lived delegated access token in Authorization: Bearer . ## Calling operations @@ -39,7 +38,7 @@ import os from dedalus_sdk import Dedalus client = Dedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), + x_api_key=os.environ.get("DEDALUS_X_API_KEY"), ) machine = client.machines.create( @@ -63,16 +62,6 @@ List endpoints return paginated results you can iterate directly; the SDK fetche page = client.machines.list() ``` -## WebSockets - -WebSocket endpoints open a persistent connection you can send messages to and receive messages from. - -```python -with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: - message = connection.recv() - print(message) -``` - ## Error handling Non-success responses throw generated API errors. Error objects expose status, headers, response body, and request metadata where the target runtime supports it. diff --git a/README.md b/README.md index a7021b4..0cd7cfb 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,6 @@ The full API of this library can be found in [api.md](./api.md). - [Usage](#usage) - [API Reference](./api.md) - [Async](#async) -- [WebSockets](#websockets) - [Authentication](#authentication) - [Errors](#errors) - [Client Options](#client-options) @@ -40,7 +39,7 @@ import os from dedalus_sdk import Dedalus client = Dedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), + x_api_key=os.environ.get("DEDALUS_X_API_KEY"), ) machine = client.machines.create( @@ -86,33 +85,19 @@ asyncio.run(main())
-## WebSockets - -WebSocket endpoints open a persistent connection you can send messages to and receive messages from. - -```python -with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: - message = connection.recv() - print(message) -``` - -
- ## Authentication Pass credentials to the generated client constructor. Environment variables are read automatically when supported by the target runtime. | Option | Type | Default | Description | | --- | --- | --- | --- | -| `x_api_key` | `string \| provider` | - | API key authentication using X-API-Key header Defaults to DEDALUS_X_API_KEY. | -| `bearer_auth` | `string \| provider` | - | Dedalus API key or short-lived delegated access token in Authorization: Bearer . Defaults to DEDALUS_BEARER_AUTH. | -| `api_key` | `string \| provider` | - | API key authentication using Bearer token Defaults to DEDALUS_API_KEY. | +| `x_api_key` | `string \| provider` | - | Dedalus API key. Alternative to Bearer token. Defaults to DEDALUS_X_API_KEY. | +| `api_key` | `string \| provider` | - | Dedalus API key or short-lived delegated access token in Authorization: Bearer . Defaults to DEDALUS_API_KEY. | Declared schemes: - `ApiKeyAuth` API key in header `x-api-key` - `BearerAuth` bearer token -- `Bearer` bearer token
@@ -155,9 +140,8 @@ client = Dedalus( | Option | Type | Default | Description | | --- | --- | --- | --- | -| `x_api_key` | `str \| None` | `os.environ.get("DEDALUS_X_API_KEY")` | API key authentication using X-API-Key header | -| `bearer_auth` | `str \| None` | `os.environ.get("DEDALUS_BEARER_AUTH")` | Dedalus API key or short-lived delegated access token in Authorization: Bearer . | -| `api_key` | `str \| None` | `os.environ.get("DEDALUS_API_KEY")` | API key authentication using Bearer token | +| `x_api_key` | `str \| None` | `os.environ.get("DEDALUS_X_API_KEY")` | Dedalus API key. Alternative to Bearer token. | +| `api_key` | `str \| None` | `os.environ.get("DEDALUS_API_KEY")` | Dedalus API key or short-lived delegated access token in Authorization: Bearer . | | `base_url` | `str \| httpx.URL \| None` | - | Override the default API base URL. | | `timeout` | `float \| Timeout \| None` | `60.0` | Maximum time in seconds to wait for a response before aborting a request. | | `max_retries` | `int` | `2` | Number of retries for temporary failures. | diff --git a/SKILL.md b/SKILL.md index 1937012..35cd7f7 100644 --- a/SKILL.md +++ b/SKILL.md @@ -21,15 +21,14 @@ import os from dedalus_sdk import Dedalus client = Dedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), + x_api_key=os.environ.get("DEDALUS_X_API_KEY"), ) ``` Provide credentials using the options below. Environment variables are read automatically when the target runtime supports them: -- `x_api_key` (env: `DEDALUS_X_API_KEY`) — API key authentication using X-API-Key header -- `bearer_auth` (env: `DEDALUS_BEARER_AUTH`) — Dedalus API key or short-lived delegated access token in Authorization: Bearer . -- `api_key` (env: `DEDALUS_API_KEY`) — API key authentication using Bearer token +- `x_api_key` (env: `DEDALUS_X_API_KEY`) — Dedalus API key. Alternative to Bearer token. +- `api_key` (env: `DEDALUS_API_KEY`) — Dedalus API key or short-lived delegated access token in Authorization: Bearer . ## Calling operations @@ -39,7 +38,7 @@ import os from dedalus_sdk import Dedalus client = Dedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), + x_api_key=os.environ.get("DEDALUS_X_API_KEY"), ) machine = client.machines.create( @@ -63,16 +62,6 @@ List endpoints return paginated results you can iterate directly; the SDK fetche page = client.machines.list() ``` -## WebSockets - -WebSocket endpoints open a persistent connection you can send messages to and receive messages from. - -```python -with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: - message = connection.recv() - print(message) -``` - ## Error handling Non-success responses throw generated API errors. Error objects expose status, headers, response body, and request metadata where the target runtime supports it. diff --git a/api.md b/api.md index e7544cf..badbc20 100644 --- a/api.md +++ b/api.md @@ -12,6 +12,7 @@ Complete reference of every operation, grouped by resource. See [the README](./R - [Destroy machine](#destroy-machine) - [Sleep a running machine](#sleep-a-running-machine) - [Wake a sleeping machine](#wake-a-sleeping-machine) + - [Reboot a machine with fresh memory](#reboot-a-machine-with-fresh-memory) - [`Machines Ssh`](#machines-ssh) - [List SSH sessions](#list-ssh-sessions) - [Create SSH session](#create-ssh-session) @@ -24,8 +25,17 @@ Complete reference of every operation, grouped by resource. See [the README](./R - [Delete execution](#delete-execution) - [Get execution output](#get-execution-output) - [List execution events](#list-execution-events) - - [`Machines Terminals`](#machines-terminals) - - [`connect`](#connect) + - [`Machines Executions Logs`](#machines-executions-logs) + - [Get execution log status](#get-execution-log-status) + - [Reauthorize execution log publication](#reauthorize-execution-log-publication) + - [Create execution log read token](#create-execution-log-read-token) + - [`Machines Autoresizing`](#machines-autoresizing) + - [Read this machine's RAM autoresizing settings](#read-this-machines-ram-autoresizing-settings) + - [Set this machine's RAM autoresizing settings](#set-this-machines-ram-autoresizing-settings) +- [`Organization`](#organization) + - [`Organization Autoresizing`](#organization-autoresizing) + - [Read organization RAM autoresizing policy](#read-organization-ram-autoresizing-policy) + - [Set organization RAM autoresizing policy](#set-organization-ram-autoresizing-policy) ## Setup @@ -35,7 +45,7 @@ import os from dedalus_sdk import Dedalus client = Dedalus( - api_key=os.environ.get("DEDALUS_API_KEY"), + x_api_key=os.environ.get("DEDALUS_X_API_KEY"), ) ``` @@ -133,6 +143,22 @@ machine = client.machines.wake( ) ``` +### Reboot a machine with fresh memory + +Checkpoints files and replaces the runtime. The machine ID and filesystem are preserved. RAM, processes, and temporary mounts are cleared. Poll the machine until its phase is running. Retry the same Idempotency-Key after a lost response. + +| Direction | Type | +| --- | --- | +| Request | [`MachineRebootParams`](./src/dedalus_sdk/types/machine_reboot_params.py) | +| Response | [`Machine`](./src/dedalus_sdk/types/machine.py) | + +```python +machine = client.machines.reboot( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + idempotency_key="", +) +``` + ### `Machines Ssh` #### List SSH sessions @@ -271,12 +297,102 @@ page = client.machines.executions.events( ) ``` -### `Machines Terminals` +#### `Machines Executions Logs` + +##### Get execution log status + +| Direction | Type | +| --- | --- | +| Response | [`Status`](./src/dedalus_sdk/types/machines/executions/status.py) | + +```python +log = client.machines.executions.logs.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", +) +``` + +##### Reauthorize execution log publication + +| Direction | Type | +| --- | --- | +| Response | [`Status`](./src/dedalus_sdk/types/machines/executions/status.py) | + +```python +log = client.machines.executions.logs.reauthorize( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", +) +``` + +##### Create execution log read token + +| Direction | Type | +| --- | --- | +| Response | [`ReadToken`](./src/dedalus_sdk/types/machines/executions/read_token.py) | + +```python +log = client.machines.executions.logs.create_token( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", +) +``` + +### `Machines Autoresizing` + +#### Read this machine's RAM autoresizing settings + +| Direction | Type | +| --- | --- | +| Response | [`Settings`](./src/dedalus_sdk/types/machines/settings.py) | + +```python +autoresizing = client.machines.autoresizing.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", +) +``` + +#### Set this machine's RAM autoresizing settings -#### `connect` +| Direction | Type | +| --- | --- | +| Request | [`AutoresizingUpdateParams`](./src/dedalus_sdk/types/machines/autoresizing_update_params.py) | +| Response | [`Settings`](./src/dedalus_sdk/types/machines/settings.py) | ```python -with client.machines.terminals.connect(machine_id="machineID", terminal_id="terminalID") as connection: - message = connection.recv() - print(message) +autoresizing = client.machines.autoresizing.update( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + enabled=False, + idempotency_key="", +) +``` + +## `Organization` + +### `Organization Autoresizing` + +#### Read organization RAM autoresizing policy + +| Direction | Type | +| --- | --- | +| Response | [`Policy`](./src/dedalus_sdk/types/organization/policy.py) | + +```python +autoresizing = client.organization.autoresizing.retrieve() +``` + +#### Set organization RAM autoresizing policy + +| Direction | Type | +| --- | --- | +| Request | [`AutoresizingUpdateParams`](./src/dedalus_sdk/types/organization/autoresizing_update_params.py) | +| Response | [`Policy`](./src/dedalus_sdk/types/organization/policy.py) | + +```python +autoresizing = client.organization.autoresizing.update( + enabled=False, + idempotency_key="", +) ``` diff --git a/pyproject.toml b/pyproject.toml index 0601588..e60f3a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,6 @@ dependencies = [ [project.optional-dependencies] aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] -websockets = ["websockets >= 13, < 16"] [build-system] requires = ["hatchling>=1.18.0"] diff --git a/scalar-sdk.manifest.json b/scalar-sdk.manifest.json index 80b6af9..0bcba7b 100644 --- a/scalar-sdk.manifest.json +++ b/scalar-sdk.manifest.json @@ -13,7 +13,6 @@ ], "auth": [ "apiKey", - "bearer", "bearer" ], "authDetails": [ @@ -27,10 +26,6 @@ "kind": "bearer", "id": "BearerAuth", "bearerFormat": "Dedalus API key or delegated access token" - }, - { - "kind": "bearer", - "id": "Bearer" } ], "clientHeaderParams": [], @@ -623,6 +618,68 @@ "additionalProperties": false } }, + { + "name": "status", + "source": "status", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "capture", + "publicName": "capture", + "required": true, + "deprecated": false, + "type": { + "kind": "ref", + "name": "machine_execution_log_capture" + } + }, + { + "name": "code", + "publicName": "code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "execution_id", + "publicName": "execution_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "publication", + "publicName": "publication", + "required": false, + "deprecated": false, + "type": { + "kind": "ref", + "name": "publication" + } + }, + { + "name": "stream_id", + "publicName": "stream_id", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, { "name": "execution_output", "source": "execution_output", @@ -1739,6 +1796,50 @@ "additionalProperties": false } }, + { + "name": "policy", + "source": "policy", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "enabled", + "publicName": "enabled", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "settings", + "source": "settings", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "enabled", + "publicName": "enabled", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + } + ], + "additionalProperties": false + } + }, { "name": "public_path_segment", "source": "public_path_segment", @@ -1754,6 +1855,152 @@ } } }, + { + "name": "publication", + "source": "publication", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "code", + "publicName": "code", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "complete", + "publicName": "complete", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "boolean" + } + }, + { + "name": "queued_messages", + "publicName": "queued_messages", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "integer", + "format": "int64", + "validation": { + "minimum": 0 + } + } + }, + { + "name": "state", + "publicName": "state", + "required": true, + "deprecated": false, + "type": { + "kind": "enum", + "values": [ + "active", + "finishing", + "failed", + "closed" + ], + "names": [ + "Active", + "Finishing", + "Failed", + "Closed" + ], + "deprecations": [ + false, + false, + false, + false + ] + } + } + ], + "additionalProperties": false + } + }, + { + "name": "read_token", + "source": "read_token", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "access_token", + "publicName": "access_token", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "base_url", + "publicName": "base_url", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "execution_id", + "publicName": "execution_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "expires_at", + "publicName": "expires_at", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string", + "format": "date-time" + } + }, + { + "name": "stream_id", + "publicName": "stream_id", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "token_type", + "publicName": "token_type", + "required": true, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, { "name": "ssh_connection", "source": "ssh_connection", @@ -3388,35 +3635,23 @@ } }, { - "name": "CreateResponseHeaders", - "source": "CreateResponseHeaders", + "name": "RebootResponseHeaders", + "source": "RebootResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ { - "name": "Idempotency-Key", - "publicName": "Idempotency-Key", + "name": "ETag", + "publicName": "ETag", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - } - ], - "additionalProperties": false - } - }, - { - "name": "CreateStatus401ResponseHeaders", - "source": "CreateStatus401ResponseHeaders", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ + }, { "name": "Idempotency-Key", "publicName": "Idempotency-Key", @@ -3426,41 +3661,57 @@ "kind": "primitive", "type": "string" } - } - ], - "additionalProperties": false - } - }, - { - "name": "CreateStatus403ResponseHeaders", - "source": "CreateStatus403ResponseHeaders", - "publicAliases": [], - "deprecated": false, - "type": { - "kind": "object", - "properties": [ + }, { - "name": "Idempotency-Key", - "publicName": "Idempotency-Key", + "name": "Location", + "publicName": "Location", "required": false, "deprecated": false, "type": { "kind": "primitive", "type": "string" } - } - ], - "additionalProperties": false + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } + } + ], + "additionalProperties": false } }, { - "name": "CreateStatus409ResponseHeaders", - "source": "CreateStatus409ResponseHeaders", + "name": "RebootResponseHeaders", + "source": "RebootResponseHeaders", "publicAliases": [], "deprecated": false, "type": { "kind": "object", "properties": [ + { + "name": "ETag", + "publicName": "ETag", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, { "name": "Idempotency-Key", "publicName": "Idempotency-Key", @@ -3470,14 +3721,42 @@ "kind": "primitive", "type": "string" } + }, + { + "name": "Location", + "publicName": "Location", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + }, + { + "name": "X-Dedalus-Storage-Operation-Id", + "publicName": "X-Dedalus-Storage-Operation-Id", + "required": false, + "deprecated": false, + "type": { + "kind": "union", + "variants": [ + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "null" + } + ] + } } ], "additionalProperties": false } }, { - "name": "CreateStatus429ResponseHeaders", - "source": "CreateStatus429ResponseHeaders", + "name": "RebootStatus401ResponseHeaders", + "source": "RebootStatus401ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { @@ -3498,8 +3777,8 @@ } }, { - "name": "CreateStatus503ResponseHeaders", - "source": "CreateStatus503ResponseHeaders", + "name": "RebootStatus403ResponseHeaders", + "source": "RebootStatus403ResponseHeaders", "publicAliases": [], "deprecated": false, "type": { @@ -3520,8 +3799,74 @@ } }, { - "name": "CreateStatusdefaultResponseHeaders", - "source": "CreateStatusdefaultResponseHeaders", + "name": "RebootStatus409ResponseHeaders", + "source": "RebootStatus409ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "RebootStatus429ResponseHeaders", + "source": "RebootStatus429ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "RebootStatus503ResponseHeaders", + "source": "RebootStatus503ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "RebootStatusdefaultResponseHeaders", + "source": "RebootStatusdefaultResponseHeaders", "publicAliases": [], "deprecated": false, "type": { @@ -3694,107 +4039,1710 @@ ], "additionalProperties": false } - } - ], - "resources": [ - "machines", - "machines.ssh", - "machines.executions", - "machines.terminals" - ], - "publicResources": [ - "machines", - "machines.ssh", - "machines.executions", - "machines.terminals" - ], - "operations": [ + }, { - "resource": "machines", - "publicResource": "machines", - "operation": "list", - "publicOperation": "list", + "name": "CreateResponseHeaders", + "source": "CreateResponseHeaders", + "publicAliases": [], "deprecated": false, - "method": "GET", - "path": "/v1/machines", - "pathParams": [], - "publicPathParams": [], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" - ], - "headerParams": [], - "publicHeaderParams": [], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, - { - "name": "cursor", - "required": false, - "style": "form", - "explode": false - } - ], - "headerParamDetails": [], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "MachineListParams" - }, - "response": { - "status": "200", - "contentType": "application/json", - "encoding": "json", - "contents": [ + "type": { + "kind": "object", + "properties": [ { - "contentType": "application/json", - "encoding": "json" + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } } - ] - }, - "responseModel": { - "name": "machine_list", - "publicAliases": [] - }, - "result": { - "successStatus": "200", - "errorStatuses": [ - "401", - "403", - "429", - "503", - "default" - ] - }, - "errorResponses": [ - { - "status": "401", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus401ResponseHeaders", + "source": "CreateStatus401ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" } - ] - }, - { - "status": "403", - "contentType": "application/json", + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus403ResponseHeaders", + "source": "CreateStatus403ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus409ResponseHeaders", + "source": "CreateStatus409ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus429ResponseHeaders", + "source": "CreateStatus429ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatus503ResponseHeaders", + "source": "CreateStatus503ResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateStatusdefaultResponseHeaders", + "source": "CreateStatusdefaultResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Idempotency-Key", + "publicName": "Idempotency-Key", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "RetrieveResponseHeaders", + "source": "RetrieveResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Cache-Control", + "publicName": "Cache-Control", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "ReauthorizeResponseHeaders", + "source": "ReauthorizeResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Cache-Control", + "publicName": "Cache-Control", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + }, + { + "name": "CreateTokenResponseHeaders", + "source": "CreateTokenResponseHeaders", + "publicAliases": [], + "deprecated": false, + "type": { + "kind": "object", + "properties": [ + { + "name": "Cache-Control", + "publicName": "Cache-Control", + "required": false, + "deprecated": false, + "type": { + "kind": "primitive", + "type": "string" + } + } + ], + "additionalProperties": false + } + } + ], + "resources": [ + "machines", + "machines.ssh", + "machines.executions", + "machines.executions.logs", + "machines.autoresizing", + "organization", + "organization.autoresizing" + ], + "publicResources": [ + "machines", + "machines.ssh", + "machines.executions", + "machines.executions.logs", + "machines.autoresizing", + "organization", + "organization.autoresizing" + ], + "operations": [ + { + "resource": "machines", + "publicResource": "machines", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines", + "pathParams": [], + "publicPathParams": [], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "machine_list_item", + "publicAliases": [] + } + }, + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "create", + "publicOperation": "create", + "deprecated": false, + "method": "POST", + "path": "/v1/machines", + "pathParams": [], + "publicPathParams": [], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "publicBodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "bodyParamDetails": [ + { + "name": "autosleep", + "required": false + }, + { + "name": "memory_mib", + "required": false + }, + { + "name": "storage_gib", + "required": false + }, + { + "name": "vcpu", + "required": false + } + ], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "CreateResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "CreateStatus401ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "CreateStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "CreateStatus409ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "CreateStatus429ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "CreateStatus503ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + }, + "headersModel": { + "name": "CreateStatusdefaultResponseHeaders", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "retrieve", + "publicOperation": "retrieve", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineRetrieveParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine_detail_response", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "RetrieveResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "update", + "publicOperation": "update", + "deprecated": false, + "method": "PATCH", + "path": "/v1/machines/{machine_id}", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "publicBodyParams": [ + "autosleep", + "memory_mib", + "storage_gib", + "vcpu" + ], + "bodyParamDetails": [ + { + "name": "autosleep", + "required": false + }, + { + "name": "memory_mib", + "required": false + }, + { + "name": "storage_gib", + "required": false + }, + { + "name": "vcpu", + "required": false + } + ], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineUpdateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "UpdateResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "UpdateStatus401ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "UpdateStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "UpdateStatus409ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "UpdateStatus429ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "UpdateStatus503ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + }, + "headersModel": { + "name": "UpdateStatusdefaultResponseHeaders", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "delete", + "publicOperation": "delete", + "deprecated": false, + "method": "DELETE", + "path": "/v1/machines/{machine_id}", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineDeleteParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "DeleteResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "DeleteStatus401ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "DeleteStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "DeleteStatus409ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "DeleteStatus429ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "DeleteStatus503ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + }, + "headersModel": { + "name": "DeleteStatusdefaultResponseHeaders", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "sleep", + "publicOperation": "sleep", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/sleep", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineSleepParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "SleepResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "SleepStatus401ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "SleepStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "SleepStatus409ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "SleepStatus429ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "SleepStatus503ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + }, + "headersModel": { + "name": "SleepStatusdefaultResponseHeaders", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "wake", + "publicOperation": "wake", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/wake", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineWakeParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "WakeResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "WakeStatus401ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "WakeStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "WakeStatus409ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "WakeStatus429ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "WakeStatus503ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + }, + "headersModel": { + "name": "WakeStatusdefaultResponseHeaders", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines", + "publicResource": "machines", + "operation": "reboot", + "publicOperation": "reboot", + "deprecated": false, + "method": "POST", + "path": "/v1/machines/{machine_id}/reboot", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [ + "force" + ], + "publicQueryParams": [ + "force" + ], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "force", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "MachineRebootParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "machine", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "RebootResponseHeaders", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "409", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "RebootStatus401ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "403", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "RebootStatus403ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "409", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "RebootStatus409ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "429", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "RebootStatus429ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "503", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "headersModel": { + "name": "RebootStatus503ResponseHeaders", + "publicAliases": [] + } + }, + { + "status": "default", + "contentType": "application/problem+json", + "encoding": "json", + "contents": [ + { + "contentType": "application/problem+json", + "encoding": "json" + } + ], + "model": { + "name": "error_model", + "publicAliases": [] + }, + "headersModel": { + "name": "RebootStatusdefaultResponseHeaders", + "publicAliases": [] + } + } + ], + "responseLinks": [], + "transport": "http" + }, + { + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "list", + "publicOperation": "list", + "deprecated": false, + "method": "GET", + "path": "/v1/machines/{machine_id}/ssh", + "pathParams": [ + "machine_id" + ], + "publicPathParams": [ + "machine_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], + "publicPositionalParams": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], + "headerParamDetails": [], + "cookieParams": [], + "publicCookieParams": [], + "cookieParamDetails": [], + "paramsModel": { + "publicName": "SshListParams" + }, + "response": { + "status": "200", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + "responseModel": { + "name": "ssh_session_list", + "publicAliases": [] + }, + "result": { + "successStatus": "200", + "errorStatuses": [ + "401", + "403", + "429", + "503", + "default" + ] + }, + "errorResponses": [ + { + "status": "401", + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ] + }, + { + "status": "403", + "contentType": "application/json", "encoding": "json", "contents": [ { @@ -3856,65 +5804,58 @@ "requestLocation": "query", "responseLocation": "body", "itemModel": { - "name": "machine_list_item", + "name": "ssh_session", "publicAliases": [] } }, "transport": "http" }, { - "resource": "machines", - "publicResource": "machines", + "resource": "machines.ssh", + "publicResource": "machines.ssh", "operation": "create", "publicOperation": "create", "deprecated": false, "method": "POST", - "path": "/v1/machines", - "pathParams": [], - "publicPathParams": [], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [], - "publicHeaderParams": [], - "bodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" + "path": "/v1/machines/{machine_id}/ssh", + "pathParams": [ + "machine_id" ], - "publicBodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" + "publicPathParams": [ + "machine_id" ], - "bodyParamDetails": [ - { - "name": "autosleep", - "required": false - }, - { - "name": "memory_mib", - "required": false - }, - { - "name": "storage_gib", - "required": false - }, + "queryParams": [], + "publicQueryParams": [], + "headerParams": [], + "publicHeaderParams": [], + "bodyParams": [ + "public_key" + ], + "publicBodyParams": [ + "public_key" + ], + "bodyParamDetails": [ { - "name": "vcpu", - "required": false + "name": "public_key", + "required": true } ], "publicPositionalParams": [], - "pathParamDetails": [], + "pathParamDetails": [ + { + "name": "machine_id", + "required": true, + "style": "simple", + "explode": false + } + ], "queryParamDetails": [], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "MachineCreateParams" + "publicName": "SshCreateParams" }, "requestBody": { "contentType": "application/json", @@ -3941,7 +5882,7 @@ ] }, "responseModel": { - "name": "machine", + "name": "ssh_session", "publicAliases": [] }, "responseHeadersModel": { @@ -4059,18 +6000,20 @@ "transport": "http" }, { - "resource": "machines", - "publicResource": "machines", + "resource": "machines.ssh", + "publicResource": "machines.ssh", "operation": "retrieve", "publicOperation": "retrieve", "deprecated": false, "method": "GET", - "path": "/v1/machines/{machine_id}", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", "pathParams": [ - "machine_id" + "machine_id", + "session_id" ], "publicPathParams": [ - "machine_id" + "machine_id", + "session_id" ], "queryParams": [], "publicQueryParams": [], @@ -4086,6 +6029,12 @@ "required": true, "style": "simple", "explode": false + }, + { + "name": "session_id", + "required": true, + "style": "simple", + "explode": false } ], "queryParamDetails": [], @@ -4094,7 +6043,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "MachineRetrieveParams" + "publicName": "SshRetrieveParams" }, "response": { "status": "200", @@ -4108,11 +6057,7 @@ ] }, "responseModel": { - "name": "machine_detail_response", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "RetrieveResponseHeaders", + "name": "ssh_session", "publicAliases": [] }, "result": { @@ -4190,53 +6135,28 @@ "transport": "http" }, { - "resource": "machines", - "publicResource": "machines", - "operation": "update", - "publicOperation": "update", + "resource": "machines.ssh", + "publicResource": "machines.ssh", + "operation": "delete", + "publicOperation": "delete", "deprecated": false, - "method": "PATCH", - "path": "/v1/machines/{machine_id}", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/ssh/{session_id}", "pathParams": [ - "machine_id" + "machine_id", + "session_id" ], "publicPathParams": [ - "machine_id" + "machine_id", + "session_id" ], "queryParams": [], "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], - "bodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" - ], - "publicBodyParams": [ - "autosleep", - "memory_mib", - "storage_gib", - "vcpu" - ], - "bodyParamDetails": [ - { - "name": "autosleep", - "required": false - }, - { - "name": "memory_mib", - "required": false - }, - { - "name": "storage_gib", - "required": false - }, - { - "name": "vcpu", - "required": false - } - ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], "publicPositionalParams": [], "pathParamDetails": [ { @@ -4244,6 +6164,12 @@ "required": true, "style": "simple", "explode": false + }, + { + "name": "session_id", + "required": true, + "style": "simple", + "explode": false } ], "queryParamDetails": [], @@ -4252,20 +6178,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "MachineUpdateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" + "publicName": "SshDeleteParams" }, "response": { "status": "200", @@ -4279,11 +6192,7 @@ ] }, "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "UpdateResponseHeaders", + "name": "ssh_session", "publicAliases": [] }, "result": { @@ -4291,7 +6200,6 @@ "errorStatuses": [ "401", "403", - "409", "429", "503", "default" @@ -4307,11 +6215,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "UpdateStatus401ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "403", @@ -4322,26 +6226,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "UpdateStatus403ResponseHeaders", - "publicAliases": [] - } - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "UpdateStatus409ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "429", @@ -4352,11 +6237,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "UpdateStatus429ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "503", @@ -4367,11 +6248,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "UpdateStatus503ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "default", @@ -4386,10 +6263,6 @@ "model": { "name": "error_model", "publicAliases": [] - }, - "headersModel": { - "name": "UpdateStatusdefaultResponseHeaders", - "publicAliases": [] } } ], @@ -4397,21 +6270,27 @@ "transport": "http" }, { - "resource": "machines", - "publicResource": "machines", - "operation": "delete", - "publicOperation": "delete", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "list", + "publicOperation": "list", "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions", "pathParams": [ "machine_id" ], "publicPathParams": [ "machine_id" ], - "queryParams": [], - "publicQueryParams": [], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" + ], "headerParams": [], "publicHeaderParams": [], "bodyParams": [], @@ -4426,13 +6305,26 @@ "explode": false } ], - "queryParamDetails": [], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "MachineDeleteParams" + "publicName": "ExecutionListParams" }, "response": { "status": "200", @@ -4446,11 +6338,7 @@ ] }, "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "DeleteResponseHeaders", + "name": "execution_list", "publicAliases": [] }, "result": { @@ -4458,7 +6346,6 @@ "errorStatuses": [ "401", "403", - "409", "429", "503", "default" @@ -4474,11 +6361,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "DeleteStatus401ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "403", @@ -4489,26 +6372,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "DeleteStatus403ResponseHeaders", - "publicAliases": [] - } - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "DeleteStatus409ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "429", @@ -4517,13 +6381,9 @@ "contents": [ { "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "DeleteStatus429ResponseHeaders", - "publicAliases": [] - } + "encoding": "json" + } + ] }, { "status": "503", @@ -4534,11 +6394,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "DeleteStatus503ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "default", @@ -4553,24 +6409,38 @@ "model": { "name": "error_model", "publicAliases": [] - }, - "headersModel": { - "name": "DeleteStatusdefaultResponseHeaders", - "publicAliases": [] } } ], "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "execution", + "publicAliases": [] + } + }, "transport": "http" }, { - "resource": "machines", - "publicResource": "machines", - "operation": "sleep", - "publicOperation": "sleep", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "create", + "publicOperation": "create", "deprecated": false, "method": "POST", - "path": "/v1/machines/{machine_id}/sleep", + "path": "/v1/machines/{machine_id}/executions", "pathParams": [ "machine_id" ], @@ -4581,9 +6451,42 @@ "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], + "bodyParams": [ + "command", + "cwd", + "env", + "stdin", + "timeout_ms" + ], + "publicBodyParams": [ + "command", + "cwd", + "env", + "stdin", + "timeout_ms" + ], + "bodyParamDetails": [ + { + "name": "command", + "required": true + }, + { + "name": "cwd", + "required": false + }, + { + "name": "env", + "required": false + }, + { + "name": "stdin", + "required": false + }, + { + "name": "timeout_ms", + "required": false + } + ], "publicPositionalParams": [], "pathParamDetails": [ { @@ -4599,7 +6502,20 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "MachineSleepParams" + "publicName": "ExecutionCreateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" }, "response": { "status": "200", @@ -4613,11 +6529,11 @@ ] }, "responseModel": { - "name": "machine", + "name": "execution", "publicAliases": [] }, "responseHeadersModel": { - "name": "SleepResponseHeaders", + "name": "CreateResponseHeaders", "publicAliases": [] }, "result": { @@ -4643,7 +6559,7 @@ } ], "headersModel": { - "name": "SleepStatus401ResponseHeaders", + "name": "CreateStatus401ResponseHeaders", "publicAliases": [] } }, @@ -4658,7 +6574,7 @@ } ], "headersModel": { - "name": "SleepStatus403ResponseHeaders", + "name": "CreateStatus403ResponseHeaders", "publicAliases": [] } }, @@ -4673,7 +6589,7 @@ } ], "headersModel": { - "name": "SleepStatus409ResponseHeaders", + "name": "CreateStatus409ResponseHeaders", "publicAliases": [] } }, @@ -4688,7 +6604,7 @@ } ], "headersModel": { - "name": "SleepStatus429ResponseHeaders", + "name": "CreateStatus429ResponseHeaders", "publicAliases": [] } }, @@ -4703,7 +6619,7 @@ } ], "headersModel": { - "name": "SleepStatus503ResponseHeaders", + "name": "CreateStatus503ResponseHeaders", "publicAliases": [] } }, @@ -4722,7 +6638,7 @@ "publicAliases": [] }, "headersModel": { - "name": "SleepStatusdefaultResponseHeaders", + "name": "CreateStatusdefaultResponseHeaders", "publicAliases": [] } } @@ -4731,18 +6647,20 @@ "transport": "http" }, { - "resource": "machines", - "publicResource": "machines", - "operation": "wake", - "publicOperation": "wake", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "retrieve", + "publicOperation": "retrieve", "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/wake", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", "pathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "publicPathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "queryParams": [], "publicQueryParams": [], @@ -4758,6 +6676,12 @@ "required": true, "style": "simple", "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false } ], "queryParamDetails": [], @@ -4766,7 +6690,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "MachineWakeParams" + "publicName": "ExecutionRetrieveParams" }, "response": { "status": "200", @@ -4780,11 +6704,7 @@ ] }, "responseModel": { - "name": "machine", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "WakeResponseHeaders", + "name": "execution", "publicAliases": [] }, "result": { @@ -4792,7 +6712,6 @@ "errorStatuses": [ "401", "403", - "409", "429", "503", "default" @@ -4808,11 +6727,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "WakeStatus401ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "403", @@ -4823,26 +6738,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "WakeStatus403ResponseHeaders", - "publicAliases": [] - } - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "WakeStatus409ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "429", @@ -4853,11 +6749,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "WakeStatus429ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "503", @@ -4868,11 +6760,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "WakeStatus503ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "default", @@ -4887,10 +6775,6 @@ "model": { "name": "error_model", "publicAliases": [] - }, - "headersModel": { - "name": "WakeStatusdefaultResponseHeaders", - "publicAliases": [] } } ], @@ -4898,27 +6782,23 @@ "transport": "http" }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "list", - "publicOperation": "list", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "delete", + "publicOperation": "delete", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/ssh", + "method": "DELETE", + "path": "/v1/machines/{machine_id}/executions/{execution_id}", "pathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "publicPathParams": [ - "machine_id" - ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" + "machine_id", + "execution_id" ], + "queryParams": [], + "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], "bodyParams": [], @@ -4931,28 +6811,21 @@ "required": true, "style": "simple", "explode": false - } - ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false }, { - "name": "cursor", - "required": false, - "style": "form", + "name": "execution_id", + "required": true, + "style": "simple", "explode": false } ], + "queryParamDetails": [], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "SshListParams" + "publicName": "ExecutionDeleteParams" }, "response": { "status": "200", @@ -4966,7 +6839,7 @@ ] }, "responseModel": { - "name": "ssh_session_list", + "name": "execution", "publicAliases": [] }, "result": { @@ -5035,62 +6908,37 @@ } ], "model": { - "name": "error_model", - "publicAliases": [] - } - } - ], - "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" - ], - "cursorParams": [ - "cursor" - ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "ssh_session", - "publicAliases": [] + "name": "error_model", + "publicAliases": [] + } } - }, + ], + "responseLinks": [], "transport": "http" }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "create", - "publicOperation": "create", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "output", + "publicOperation": "output", "deprecated": false, - "method": "POST", - "path": "/v1/machines/{machine_id}/ssh", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", "pathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "publicPathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "queryParams": [], "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], - "bodyParams": [ - "public_key" - ], - "publicBodyParams": [ - "public_key" - ], - "bodyParamDetails": [ - { - "name": "public_key", - "required": true - } - ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], "publicPositionalParams": [], "pathParamDetails": [ { @@ -5098,6 +6946,12 @@ "required": true, "style": "simple", "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false } ], "queryParamDetails": [], @@ -5106,20 +6960,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "SshCreateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" + "publicName": "ExecutionOutputParams" }, "response": { "status": "200", @@ -5133,11 +6974,7 @@ ] }, "responseModel": { - "name": "ssh_session", - "publicAliases": [] - }, - "responseHeadersModel": { - "name": "CreateResponseHeaders", + "name": "execution_output", "publicAliases": [] }, "result": { @@ -5145,7 +6982,6 @@ "errorStatuses": [ "401", "403", - "409", "429", "503", "default" @@ -5161,11 +6997,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "CreateStatus401ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "403", @@ -5176,26 +7008,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "CreateStatus403ResponseHeaders", - "publicAliases": [] - } - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "CreateStatus409ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "429", @@ -5206,11 +7019,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "CreateStatus429ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "503", @@ -5221,11 +7030,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "CreateStatus503ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "default", @@ -5240,10 +7045,6 @@ "model": { "name": "error_model", "publicAliases": [] - }, - "headersModel": { - "name": "CreateStatusdefaultResponseHeaders", - "publicAliases": [] } } ], @@ -5251,23 +7052,29 @@ "transport": "http" }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "retrieve", - "publicOperation": "retrieve", + "resource": "machines.executions", + "publicResource": "machines.executions", + "operation": "events", + "publicOperation": "events", "deprecated": false, "method": "GET", - "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", "pathParams": [ "machine_id", - "session_id" + "execution_id" ], "publicPathParams": [ "machine_id", - "session_id" + "execution_id" + ], + "queryParams": [ + "limit", + "cursor" + ], + "publicQueryParams": [ + "limit", + "cursor" ], - "queryParams": [], - "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], "bodyParams": [], @@ -5282,19 +7089,32 @@ "explode": false }, { - "name": "session_id", + "name": "execution_id", "required": true, "style": "simple", "explode": false } ], - "queryParamDetails": [], + "queryParamDetails": [ + { + "name": "limit", + "required": false, + "style": "form", + "explode": false + }, + { + "name": "cursor", + "required": false, + "style": "form", + "explode": false + } + ], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "SshRetrieveParams" + "publicName": "ExecutionEventsParams" }, "response": { "status": "200", @@ -5308,7 +7128,7 @@ ] }, "responseModel": { - "name": "ssh_session", + "name": "execution_events", "publicAliases": [] }, "result": { @@ -5383,23 +7203,41 @@ } ], "responseLinks": [], + "pagination": { + "style": "cursor", + "itemsField": "items", + "cursorField": "next_cursor", + "cursorParam": "cursor", + "cursorFields": [ + "next_cursor" + ], + "cursorParams": [ + "cursor" + ], + "requestLocation": "query", + "responseLocation": "body", + "itemModel": { + "name": "execution_event", + "publicAliases": [] + } + }, "transport": "http" }, { - "resource": "machines.ssh", - "publicResource": "machines.ssh", - "operation": "delete", - "publicOperation": "delete", + "resource": "machines.executions.logs", + "publicResource": "machines.executions.logs", + "operation": "retrieve", + "publicOperation": "retrieve", "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}/ssh/{session_id}", + "method": "GET", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/logs", "pathParams": [ "machine_id", - "session_id" + "execution_id" ], "publicPathParams": [ "machine_id", - "session_id" + "execution_id" ], "queryParams": [], "publicQueryParams": [], @@ -5417,7 +7255,7 @@ "explode": false }, { - "name": "session_id", + "name": "execution_id", "required": true, "style": "simple", "explode": false @@ -5429,7 +7267,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "SshDeleteParams" + "publicName": "LogRetrieveParams" }, "response": { "status": "200", @@ -5443,7 +7281,11 @@ ] }, "responseModel": { - "name": "ssh_session", + "name": "status", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "RetrieveResponseHeaders", "publicAliases": [] }, "result": { @@ -5451,8 +7293,6 @@ "errorStatuses": [ "401", "403", - "429", - "503", "default" ] }, @@ -5479,28 +7319,6 @@ } ] }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "default", "contentType": "application/problem+json", @@ -5521,27 +7339,23 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "list", - "publicOperation": "list", + "resource": "machines.executions.logs", + "publicResource": "machines.executions.logs", + "operation": "reauthorize", + "publicOperation": "reauthorize", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/executions", + "method": "POST", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/logs/reauthorize", "pathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "publicPathParams": [ - "machine_id" - ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" + "machine_id", + "execution_id" ], + "queryParams": [], + "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], "bodyParams": [], @@ -5554,28 +7368,21 @@ "required": true, "style": "simple", "explode": false - } - ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false }, { - "name": "cursor", - "required": false, - "style": "form", + "name": "execution_id", + "required": true, + "style": "simple", "explode": false } ], + "queryParamDetails": [], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionListParams" + "publicName": "LogReauthorizeParams" }, "response": { "status": "200", @@ -5589,7 +7396,11 @@ ] }, "responseModel": { - "name": "execution_list", + "name": "status", + "publicAliases": [] + }, + "responseHeadersModel": { + "name": "ReauthorizeResponseHeaders", "publicAliases": [] }, "result": { @@ -5597,8 +7408,6 @@ "errorStatuses": [ "401", "403", - "429", - "503", "default" ] }, @@ -5625,28 +7434,6 @@ } ] }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "default", "contentType": "application/problem+json", @@ -5664,80 +7451,31 @@ } ], "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" - ], - "cursorParams": [ - "cursor" - ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "execution", - "publicAliases": [] - } - }, "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "create", - "publicOperation": "create", + "resource": "machines.executions.logs", + "publicResource": "machines.executions.logs", + "operation": "createToken", + "publicOperation": "createToken", "deprecated": false, "method": "POST", - "path": "/v1/machines/{machine_id}/executions", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/logs/token", "pathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "publicPathParams": [ - "machine_id" + "machine_id", + "execution_id" ], "queryParams": [], "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], - "bodyParams": [ - "command", - "cwd", - "env", - "stdin", - "timeout_ms" - ], - "publicBodyParams": [ - "command", - "cwd", - "env", - "stdin", - "timeout_ms" - ], - "bodyParamDetails": [ - { - "name": "command", - "required": true - }, - { - "name": "cwd", - "required": false - }, - { - "name": "env", - "required": false - }, - { - "name": "stdin", - "required": false - }, - { - "name": "timeout_ms", - "required": false - } - ], + "bodyParams": [], + "publicBodyParams": [], + "bodyParamDetails": [], "publicPositionalParams": [], "pathParamDetails": [ { @@ -5745,6 +7483,12 @@ "required": true, "style": "simple", "explode": false + }, + { + "name": "execution_id", + "required": true, + "style": "simple", + "explode": false } ], "queryParamDetails": [], @@ -5753,20 +7497,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionCreateParams" - }, - "requestBody": { - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "required": true, - "publicName": "body", - "publicIdentifier": "body" + "publicName": "LogCreateTokenParams" }, "response": { "status": "200", @@ -5780,11 +7511,11 @@ ] }, "responseModel": { - "name": "execution", + "name": "read_token", "publicAliases": [] }, "responseHeadersModel": { - "name": "CreateResponseHeaders", + "name": "CreateTokenResponseHeaders", "publicAliases": [] }, "result": { @@ -5792,9 +7523,6 @@ "errorStatuses": [ "401", "403", - "409", - "429", - "503", "default" ] }, @@ -5808,11 +7536,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "CreateStatus401ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "403", @@ -5823,56 +7547,7 @@ "contentType": "application/json", "encoding": "json" } - ], - "headersModel": { - "name": "CreateStatus403ResponseHeaders", - "publicAliases": [] - } - }, - { - "status": "409", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "CreateStatus409ResponseHeaders", - "publicAliases": [] - } - }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "CreateStatus429ResponseHeaders", - "publicAliases": [] - } - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ], - "headersModel": { - "name": "CreateStatus503ResponseHeaders", - "publicAliases": [] - } + ] }, { "status": "default", @@ -5887,10 +7562,6 @@ "model": { "name": "error_model", "publicAliases": [] - }, - "headersModel": { - "name": "CreateStatusdefaultResponseHeaders", - "publicAliases": [] } } ], @@ -5898,20 +7569,18 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", + "resource": "machines.autoresizing", + "publicResource": "machines.autoresizing", "operation": "retrieve", "publicOperation": "retrieve", "deprecated": false, "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "path": "/v1/machines/{machine_id}/autoresizing", "pathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "queryParams": [], "publicQueryParams": [], @@ -5927,12 +7596,6 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false } ], "queryParamDetails": [], @@ -5941,7 +7604,7 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionRetrieveParams" + "publicName": "AutoresizingRetrieveParams" }, "response": { "status": "200", @@ -5955,7 +7618,7 @@ ] }, "responseModel": { - "name": "execution", + "name": "settings", "publicAliases": [] }, "result": { @@ -5963,8 +7626,6 @@ "errorStatuses": [ "401", "403", - "429", - "503", "default" ] }, @@ -5991,28 +7652,6 @@ } ] }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "default", "contentType": "application/problem+json", @@ -6033,28 +7672,35 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "delete", - "publicOperation": "delete", + "resource": "machines.autoresizing", + "publicResource": "machines.autoresizing", + "operation": "update", + "publicOperation": "update", "deprecated": false, - "method": "DELETE", - "path": "/v1/machines/{machine_id}/executions/{execution_id}", + "method": "PUT", + "path": "/v1/machines/{machine_id}/autoresizing", "pathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "publicPathParams": [ - "machine_id", - "execution_id" + "machine_id" ], "queryParams": [], "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], + "bodyParams": [ + "enabled" + ], + "publicBodyParams": [ + "enabled" + ], + "bodyParamDetails": [ + { + "name": "enabled", + "required": true + } + ], "publicPositionalParams": [], "pathParamDetails": [ { @@ -6062,12 +7708,6 @@ "required": true, "style": "simple", "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false } ], "queryParamDetails": [], @@ -6076,7 +7716,20 @@ "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionDeleteParams" + "publicName": "AutoresizingUpdateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" }, "response": { "status": "200", @@ -6090,7 +7743,7 @@ ] }, "responseModel": { - "name": "execution", + "name": "settings", "publicAliases": [] }, "result": { @@ -6098,8 +7751,6 @@ "errorStatuses": [ "401", "403", - "429", - "503", "default" ] }, @@ -6126,28 +7777,6 @@ } ] }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "default", "contentType": "application/problem+json", @@ -6168,21 +7797,15 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "output", - "publicOperation": "output", + "resource": "organization.autoresizing", + "publicResource": "organization.autoresizing", + "operation": "retrieve", + "publicOperation": "retrieve", "deprecated": false, "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", - "pathParams": [ - "machine_id", - "execution_id" - ], - "publicPathParams": [ - "machine_id", - "execution_id" - ], + "path": "/v1/organization/autoresizing", + "pathParams": [], + "publicPathParams": [], "queryParams": [], "publicQueryParams": [], "headerParams": [], @@ -6191,28 +7814,12 @@ "publicBodyParams": [], "bodyParamDetails": [], "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false - } - ], + "pathParamDetails": [], "queryParamDetails": [], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], - "paramsModel": { - "publicName": "ExecutionOutputParams" - }, "response": { "status": "200", "contentType": "application/json", @@ -6225,7 +7832,7 @@ ] }, "responseModel": { - "name": "execution_output", + "name": "policy", "publicAliases": [] }, "result": { @@ -6233,8 +7840,6 @@ "errorStatuses": [ "401", "403", - "429", - "503", "default" ] }, @@ -6261,28 +7866,6 @@ } ] }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "default", "contentType": "application/problem+json", @@ -6303,69 +7886,53 @@ "transport": "http" }, { - "resource": "machines.executions", - "publicResource": "machines.executions", - "operation": "events", - "publicOperation": "events", + "resource": "organization.autoresizing", + "publicResource": "organization.autoresizing", + "operation": "update", + "publicOperation": "update", "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", - "pathParams": [ - "machine_id", - "execution_id" - ], - "publicPathParams": [ - "machine_id", - "execution_id" - ], - "queryParams": [ - "limit", - "cursor" - ], - "publicQueryParams": [ - "limit", - "cursor" - ], + "method": "PUT", + "path": "/v1/organization/autoresizing", + "pathParams": [], + "publicPathParams": [], + "queryParams": [], + "publicQueryParams": [], "headerParams": [], "publicHeaderParams": [], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true, - "style": "simple", - "explode": false - }, - { - "name": "execution_id", - "required": true, - "style": "simple", - "explode": false - } + "bodyParams": [ + "enabled" ], - "queryParamDetails": [ - { - "name": "limit", - "required": false, - "style": "form", - "explode": false - }, + "publicBodyParams": [ + "enabled" + ], + "bodyParamDetails": [ { - "name": "cursor", - "required": false, - "style": "form", - "explode": false + "name": "enabled", + "required": true } ], + "publicPositionalParams": [], + "pathParamDetails": [], + "queryParamDetails": [], "headerParamDetails": [], "cookieParams": [], "publicCookieParams": [], "cookieParamDetails": [], "paramsModel": { - "publicName": "ExecutionEventsParams" + "publicName": "AutoresizingUpdateParams" + }, + "requestBody": { + "contentType": "application/json", + "encoding": "json", + "contents": [ + { + "contentType": "application/json", + "encoding": "json" + } + ], + "required": true, + "publicName": "body", + "publicIdentifier": "body" }, "response": { "status": "200", @@ -6379,7 +7946,7 @@ ] }, "responseModel": { - "name": "execution_events", + "name": "policy", "publicAliases": [] }, "result": { @@ -6387,8 +7954,6 @@ "errorStatuses": [ "401", "403", - "429", - "503", "default" ] }, @@ -6415,28 +7980,6 @@ } ] }, - { - "status": "429", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, - { - "status": "503", - "contentType": "application/json", - "encoding": "json", - "contents": [ - { - "contentType": "application/json", - "encoding": "json" - } - ] - }, { "status": "default", "contentType": "application/problem+json", @@ -6454,74 +7997,7 @@ } ], "responseLinks": [], - "pagination": { - "style": "cursor", - "itemsField": "items", - "cursorField": "next_cursor", - "cursorParam": "cursor", - "cursorFields": [ - "next_cursor" - ], - "cursorParams": [ - "cursor" - ], - "requestLocation": "query", - "responseLocation": "body", - "itemModel": { - "name": "execution_event", - "publicAliases": [] - } - }, "transport": "http" - }, - { - "resource": "machines.terminals", - "publicResource": "machines.terminals", - "operation": "connect", - "publicOperation": "connect", - "deprecated": false, - "method": "GET", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", - "pathParams": [ - "machine_id", - "terminal_id" - ], - "publicPathParams": [ - "machine_id", - "terminal_id" - ], - "queryParams": [], - "publicQueryParams": [], - "headerParams": [], - "publicHeaderParams": [], - "bodyParams": [], - "publicBodyParams": [], - "bodyParamDetails": [], - "publicPositionalParams": [], - "pathParamDetails": [ - { - "name": "machine_id", - "required": true - }, - { - "name": "terminal_id", - "required": true - } - ], - "queryParamDetails": [], - "headerParamDetails": [], - "cookieParams": [], - "publicCookieParams": [], - "cookieParamDetails": [], - "paramsModel": { - "publicName": "TerminalConnectParams" - }, - "errorResponses": [], - "responseLinks": [], - "transport": "websocket", - "websocket": { - "eventNameSeparator": "." - } } ], "webhooks": [] diff --git a/src/dedalus_sdk/__init__.py b/src/dedalus_sdk/__init__.py index 6521cc0..e864e41 100644 --- a/src/dedalus_sdk/__init__.py +++ b/src/dedalus_sdk/__init__.py @@ -24,13 +24,10 @@ InternalServerError, PermissionDeniedError, UnprocessableEntityError, - WebSocketConnectionClosedError, - WebSocketQueueFullError, APIResponseValidationError, ) from ._base_client import DefaultHttpxClient, DefaultAioHttpClient, DefaultAsyncHttpxClient from ._utils._logs import setup_logging as _setup_logging -from .types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides __all__ = [ "types", @@ -74,10 +71,6 @@ "DefaultHttpxClient", "DefaultAsyncHttpxClient", "DefaultAioHttpClient", - "ReconnectingEvent", - "ReconnectingOverrides", - "WebSocketQueueFullError", - "WebSocketConnectionClosedError", ] if not _t.TYPE_CHECKING: diff --git a/src/dedalus_sdk/_client.py b/src/dedalus_sdk/_client.py index 5cf4d36..2f55530 100644 --- a/src/dedalus_sdk/_client.py +++ b/src/dedalus_sdk/_client.py @@ -33,8 +33,9 @@ from ._version import __version__ if TYPE_CHECKING: - from .resources import machines + from .resources import machines, organization from .resources.machines import MachinesResource, AsyncMachinesResource + from .resources.organization import OrganizationResource, AsyncOrganizationResource # Serializes lazy resource imports so concurrent cold access from multiple # threads cannot deadlock on CPython import locks (see CPython 3.14). @@ -49,18 +50,6 @@ class Dedalus(SyncAPIClient): x_api_key: str | None as_base_url: str | None dedalus_org_id: str | None - provider: str | None - provider_key: str | None - provider_model: str | None - bearer_auth: str | None - - websocket_base_url: str | httpx.URL | None - """Base URL for WebSocket connections. - - If not specified, the default base URL will be used, with 'wss://' replacing the - 'http://' or 'https://' scheme. For example: 'http://example.com' becomes - 'wss://example.com' - """ def __init__( self, @@ -69,12 +58,7 @@ def __init__( x_api_key: str | None = None, as_base_url: str | None = None, dedalus_org_id: str | None = None, - provider: str | None = None, - provider_key: str | None = None, - provider_model: str | None = None, - bearer_auth: str | None = None, base_url: str | httpx.URL | None = None, - websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, @@ -100,9 +84,6 @@ def __init__( - `x_api_key` from `DEDALUS_X_API_KEY` - `as_base_url` from `DEDALUS_AS_URL` - `dedalus_org_id` from `DEDALUS_ORG_ID` - - `provider` from `DEDALUS_PROVIDER` - - `provider_key` from `DEDALUS_PROVIDER_KEY` - - `provider_model` from `DEDALUS_PROVIDER_MODEL` """ if api_key is None: api_key = os.environ.get("DEDALUS_API_KEY") @@ -118,19 +99,6 @@ def __init__( if dedalus_org_id is None: dedalus_org_id = os.environ.get("DEDALUS_ORG_ID") self.dedalus_org_id = dedalus_org_id - if provider is None: - provider = os.environ.get("DEDALUS_PROVIDER") - self.provider = provider - if provider_key is None: - provider_key = os.environ.get("DEDALUS_PROVIDER_KEY") - self.provider_key = provider_key - if provider_model is None: - provider_model = os.environ.get("DEDALUS_PROVIDER_MODEL") - self.provider_model = provider_model - if bearer_auth is None: - bearer_auth = os.environ.get("DEDALUS_BEARER_AUTH") - self.bearer_auth = bearer_auth - self.websocket_base_url = websocket_base_url if base_url is None: base_url = os.environ.get("DEDALUS_BASE_URL") if base_url is None: @@ -162,6 +130,12 @@ def machines(self) -> "MachinesResource": from .resources.machines import MachinesResource return MachinesResource(self) + @cached_property + def organization(self) -> "OrganizationResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.organization import OrganizationResource + return OrganizationResource(self) + @cached_property def with_raw_response(self) -> DedalusWithRawResponse: return DedalusWithRawResponse(self) @@ -181,7 +155,6 @@ def auth_headers(self) -> dict[str, str]: return { **self._api_key_header_auth, **self._x_api_key_header_auth, - **self._bearer_auth_header_auth, } @override @@ -208,13 +181,6 @@ def _x_api_key_header_auth(self) -> dict[str, str]: return {} return {"x-api-key": value} - @property - def _bearer_auth_header_auth(self) -> dict[str, str]: - value = self.bearer_auth - if value is None: - return {} - return {"Authorization": f"Bearer {value}"} - @property @override def default_headers(self) -> dict[str, str | Omit]: @@ -223,9 +189,6 @@ def default_headers(self) -> dict[str, str | Omit]: "X-Scalar-Async": "false", "User-Agent": "Dedalus-SDK", "X-SDK-Version": "1.0.0", - "X-Provider": self.provider if self.provider is not None else Omit(), - "X-Provider-Key": self.provider_key if self.provider_key is not None else Omit(), - "X-Provider-Model": self.provider_model if self.provider_model is not None else Omit(), **self._custom_headers, } @@ -246,7 +209,7 @@ def _validate_headers( if isinstance(custom_headers.get("x-api-key"), Omit): return raise TypeError( - '"Could not resolve authentication method. Expected either api_key, bearer_auth or x_api_key to be set. Or for one of the `Authorization` or `x-api-key` headers to be explicitly omitted"' + '"Could not resolve authentication method. Expected either api_key or x_api_key to be set. Or for one of the `Authorization` or `x-api-key` headers to be explicitly omitted"' ) def copy( @@ -256,11 +219,6 @@ def copy( x_api_key: str | None = None, as_base_url: str | None = None, dedalus_org_id: str | None = None, - provider: str | None = None, - provider_key: str | None = None, - provider_model: str | None = None, - bearer_auth: str | None = None, - websocket_base_url: str | httpx.URL | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.Client | None = None, @@ -292,11 +250,6 @@ def copy( x_api_key=x_api_key or self.x_api_key, as_base_url=as_base_url or self.as_base_url, dedalus_org_id=dedalus_org_id or self.dedalus_org_id, - provider=provider or self.provider, - provider_key=provider_key or self.provider_key, - provider_model=provider_model or self.provider_model, - bearer_auth=bearer_auth or self.bearer_auth, - websocket_base_url=websocket_base_url or self.websocket_base_url, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, @@ -336,18 +289,6 @@ class AsyncDedalus(AsyncAPIClient): x_api_key: str | None as_base_url: str | None dedalus_org_id: str | None - provider: str | None - provider_key: str | None - provider_model: str | None - bearer_auth: str | None - - websocket_base_url: str | httpx.URL | None - """Base URL for WebSocket connections. - - If not specified, the default base URL will be used, with 'wss://' replacing the - 'http://' or 'https://' scheme. For example: 'http://example.com' becomes - 'wss://example.com' - """ def __init__( self, @@ -356,12 +297,7 @@ def __init__( x_api_key: str | None = None, as_base_url: str | None = None, dedalus_org_id: str | None = None, - provider: str | None = None, - provider_key: str | None = None, - provider_model: str | None = None, - bearer_auth: str | None = None, base_url: str | httpx.URL | None = None, - websocket_base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, max_retries: int = DEFAULT_MAX_RETRIES, default_headers: Mapping[str, str] | None = None, @@ -387,9 +323,6 @@ def __init__( - `x_api_key` from `DEDALUS_X_API_KEY` - `as_base_url` from `DEDALUS_AS_URL` - `dedalus_org_id` from `DEDALUS_ORG_ID` - - `provider` from `DEDALUS_PROVIDER` - - `provider_key` from `DEDALUS_PROVIDER_KEY` - - `provider_model` from `DEDALUS_PROVIDER_MODEL` """ if api_key is None: api_key = os.environ.get("DEDALUS_API_KEY") @@ -405,19 +338,6 @@ def __init__( if dedalus_org_id is None: dedalus_org_id = os.environ.get("DEDALUS_ORG_ID") self.dedalus_org_id = dedalus_org_id - if provider is None: - provider = os.environ.get("DEDALUS_PROVIDER") - self.provider = provider - if provider_key is None: - provider_key = os.environ.get("DEDALUS_PROVIDER_KEY") - self.provider_key = provider_key - if provider_model is None: - provider_model = os.environ.get("DEDALUS_PROVIDER_MODEL") - self.provider_model = provider_model - if bearer_auth is None: - bearer_auth = os.environ.get("DEDALUS_BEARER_AUTH") - self.bearer_auth = bearer_auth - self.websocket_base_url = websocket_base_url if base_url is None: base_url = os.environ.get("DEDALUS_BASE_URL") if base_url is None: @@ -449,6 +369,12 @@ def machines(self) -> "AsyncMachinesResource": from .resources.machines import AsyncMachinesResource return AsyncMachinesResource(self) + @cached_property + def organization(self) -> "AsyncOrganizationResource": + with _RESOURCE_IMPORT_LOCK: + from .resources.organization import AsyncOrganizationResource + return AsyncOrganizationResource(self) + @cached_property def with_raw_response(self) -> AsyncDedalusWithRawResponse: return AsyncDedalusWithRawResponse(self) @@ -468,7 +394,6 @@ def auth_headers(self) -> dict[str, str]: return { **self._api_key_header_auth, **self._x_api_key_header_auth, - **self._bearer_auth_header_auth, } @override @@ -495,13 +420,6 @@ def _x_api_key_header_auth(self) -> dict[str, str]: return {} return {"x-api-key": value} - @property - def _bearer_auth_header_auth(self) -> dict[str, str]: - value = self.bearer_auth - if value is None: - return {} - return {"Authorization": f"Bearer {value}"} - @property @override def default_headers(self) -> dict[str, str | Omit]: @@ -510,9 +428,6 @@ def default_headers(self) -> dict[str, str | Omit]: "X-Scalar-Async": f"async:{get_async_library()}", "User-Agent": "Dedalus-SDK", "X-SDK-Version": "1.0.0", - "X-Provider": self.provider if self.provider is not None else Omit(), - "X-Provider-Key": self.provider_key if self.provider_key is not None else Omit(), - "X-Provider-Model": self.provider_model if self.provider_model is not None else Omit(), **self._custom_headers, } @@ -533,7 +448,7 @@ def _validate_headers( if isinstance(custom_headers.get("x-api-key"), Omit): return raise TypeError( - '"Could not resolve authentication method. Expected either api_key, bearer_auth or x_api_key to be set. Or for one of the `Authorization` or `x-api-key` headers to be explicitly omitted"' + '"Could not resolve authentication method. Expected either api_key or x_api_key to be set. Or for one of the `Authorization` or `x-api-key` headers to be explicitly omitted"' ) def copy( @@ -543,11 +458,6 @@ def copy( x_api_key: str | None = None, as_base_url: str | None = None, dedalus_org_id: str | None = None, - provider: str | None = None, - provider_key: str | None = None, - provider_model: str | None = None, - bearer_auth: str | None = None, - websocket_base_url: str | httpx.URL | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = not_given, http_client: httpx.AsyncClient | None = None, @@ -579,11 +489,6 @@ def copy( x_api_key=x_api_key or self.x_api_key, as_base_url=as_base_url or self.as_base_url, dedalus_org_id=dedalus_org_id or self.dedalus_org_id, - provider=provider or self.provider, - provider_key=provider_key or self.provider_key, - provider_model=provider_model or self.provider_model, - bearer_auth=bearer_auth or self.bearer_auth, - websocket_base_url=websocket_base_url or self.websocket_base_url, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, @@ -629,6 +534,12 @@ def machines(self) -> machines.MachinesResourceWithRawResponse: from .resources.machines import MachinesResourceWithRawResponse return MachinesResourceWithRawResponse(self._client.machines) + @cached_property + def organization(self) -> organization.OrganizationResourceWithRawResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.organization import OrganizationResourceWithRawResponse + return OrganizationResourceWithRawResponse(self._client.organization) + class AsyncDedalusWithRawResponse: _client: AsyncDedalus @@ -642,6 +553,12 @@ def machines(self) -> machines.AsyncMachinesResourceWithRawResponse: from .resources.machines import AsyncMachinesResourceWithRawResponse return AsyncMachinesResourceWithRawResponse(self._client.machines) + @cached_property + def organization(self) -> organization.AsyncOrganizationResourceWithRawResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.organization import AsyncOrganizationResourceWithRawResponse + return AsyncOrganizationResourceWithRawResponse(self._client.organization) + class DedalusWithStreamedResponse: _client: Dedalus @@ -655,6 +572,12 @@ def machines(self) -> machines.MachinesResourceWithStreamingResponse: from .resources.machines import MachinesResourceWithStreamingResponse return MachinesResourceWithStreamingResponse(self._client.machines) + @cached_property + def organization(self) -> organization.OrganizationResourceWithStreamingResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.organization import OrganizationResourceWithStreamingResponse + return OrganizationResourceWithStreamingResponse(self._client.organization) + class AsyncDedalusWithStreamedResponse: _client: AsyncDedalus @@ -668,6 +591,12 @@ def machines(self) -> machines.AsyncMachinesResourceWithStreamingResponse: from .resources.machines import AsyncMachinesResourceWithStreamingResponse return AsyncMachinesResourceWithStreamingResponse(self._client.machines) + @cached_property + def organization(self) -> organization.AsyncOrganizationResourceWithStreamingResponse: + with _RESOURCE_IMPORT_LOCK: + from .resources.organization import AsyncOrganizationResourceWithStreamingResponse + return AsyncOrganizationResourceWithStreamingResponse(self._client.organization) + # Alias names for the documented `Client` / `AsyncClient` symbols. Client = Dedalus diff --git a/src/dedalus_sdk/resources/__init__.py b/src/dedalus_sdk/resources/__init__.py index a514d0c..164b6bd 100644 --- a/src/dedalus_sdk/resources/__init__.py +++ b/src/dedalus_sdk/resources/__init__.py @@ -8,6 +8,14 @@ MachinesResourceWithStreamingResponse, AsyncMachinesResourceWithStreamingResponse, ) +from .organization import ( + OrganizationResource, + AsyncOrganizationResource, + OrganizationResourceWithRawResponse, + AsyncOrganizationResourceWithRawResponse, + OrganizationResourceWithStreamingResponse, + AsyncOrganizationResourceWithStreamingResponse, +) __all__ = [ "MachinesResource", @@ -16,4 +24,10 @@ "AsyncMachinesResourceWithRawResponse", "MachinesResourceWithStreamingResponse", "AsyncMachinesResourceWithStreamingResponse", + "OrganizationResource", + "AsyncOrganizationResource", + "OrganizationResourceWithRawResponse", + "AsyncOrganizationResourceWithRawResponse", + "OrganizationResourceWithStreamingResponse", + "AsyncOrganizationResourceWithStreamingResponse", ] diff --git a/src/dedalus_sdk/resources/machines/__init__.py b/src/dedalus_sdk/resources/machines/__init__.py index 24b07c4..ec0b2de 100644 --- a/src/dedalus_sdk/resources/machines/__init__.py +++ b/src/dedalus_sdk/resources/machines/__init__.py @@ -24,13 +24,13 @@ ExecutionsResourceWithStreamingResponse, AsyncExecutionsResourceWithStreamingResponse, ) -from .terminals import ( - TerminalsResource, - AsyncTerminalsResource, - TerminalsResourceWithRawResponse, - AsyncTerminalsResourceWithRawResponse, - TerminalsResourceWithStreamingResponse, - AsyncTerminalsResourceWithStreamingResponse, +from .autoresizing import ( + AutoresizingResource, + AsyncAutoresizingResource, + AutoresizingResourceWithRawResponse, + AsyncAutoresizingResourceWithRawResponse, + AutoresizingResourceWithStreamingResponse, + AsyncAutoresizingResourceWithStreamingResponse, ) __all__ = [ @@ -52,10 +52,10 @@ "AsyncExecutionsResourceWithRawResponse", "ExecutionsResourceWithStreamingResponse", "AsyncExecutionsResourceWithStreamingResponse", - "TerminalsResource", - "AsyncTerminalsResource", - "TerminalsResourceWithRawResponse", - "AsyncTerminalsResourceWithRawResponse", - "TerminalsResourceWithStreamingResponse", - "AsyncTerminalsResourceWithStreamingResponse", + "AutoresizingResource", + "AsyncAutoresizingResource", + "AutoresizingResourceWithRawResponse", + "AsyncAutoresizingResourceWithRawResponse", + "AutoresizingResourceWithStreamingResponse", + "AsyncAutoresizingResourceWithStreamingResponse", ] diff --git a/src/dedalus_sdk/resources/machines/autoresizing.py b/src/dedalus_sdk/resources/machines/autoresizing.py new file mode 100644 index 0000000..7d2899f --- /dev/null +++ b/src/dedalus_sdk/resources/machines/autoresizing.py @@ -0,0 +1,281 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Query, Headers, NotGiven, 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 ..._base_client import make_request_options +from ...types.machines.settings import Settings +from ...types.machines import autoresizing_update_params + +__all__ = ["AutoresizingResource", "AsyncAutoresizingResource"] + + +class AutoresizingResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AutoresizingResourceWithRawResponse: + return AutoresizingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AutoresizingResourceWithStreamingResponse: + return AutoresizingResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + machine_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Settings: + """ + Read this machine's RAM autoresizing settings + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Settings: OK + + Example: + ```python + autoresizing = client.machines.autoresizing.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + return self._get( + path_template("/v1/machines/{machine_id}/autoresizing", **{"machine_id": machine_id}), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Settings, + ) + + def update( + self, + *, + machine_id: str, + enabled: bool, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> Settings: + """ + Set this machine's RAM autoresizing settings + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + enabled: Body parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Settings: OK + + Example: + ```python + autoresizing = client.machines.autoresizing.update( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + enabled=False, + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + return self._put( + path_template("/v1/machines/{machine_id}/autoresizing", **{"machine_id": machine_id}), + body=maybe_transform( + {"enabled": enabled}, + autoresizing_update_params.AutoresizingUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Settings, + ) + + +class AsyncAutoresizingResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAutoresizingResourceWithRawResponse: + return AsyncAutoresizingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAutoresizingResourceWithStreamingResponse: + return AsyncAutoresizingResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + machine_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Settings: + """ + Read this machine's RAM autoresizing settings + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Settings: OK + + Example: + ```python + autoresizing = await client.machines.autoresizing.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + return await self._get( + path_template("/v1/machines/{machine_id}/autoresizing", **{"machine_id": machine_id}), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Settings, + ) + + async def update( + self, + *, + machine_id: str, + enabled: bool, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> Settings: + """ + Set this machine's RAM autoresizing settings + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + enabled: Body parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Settings: OK + + Example: + ```python + autoresizing = await client.machines.autoresizing.update( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + enabled=False, + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + return await self._put( + path_template("/v1/machines/{machine_id}/autoresizing", **{"machine_id": machine_id}), + body=await async_maybe_transform( + {"enabled": enabled}, + autoresizing_update_params.AutoresizingUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Settings, + ) + + +class AutoresizingResourceWithRawResponse: + def __init__(self, autoresizing: AutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = to_raw_response_wrapper( + autoresizing.retrieve, + ) + self.update = to_raw_response_wrapper( + autoresizing.update, + ) + + +class AsyncAutoresizingResourceWithRawResponse: + def __init__(self, autoresizing: AsyncAutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = async_to_raw_response_wrapper( + autoresizing.retrieve, + ) + self.update = async_to_raw_response_wrapper( + autoresizing.update, + ) + + +class AutoresizingResourceWithStreamingResponse: + def __init__(self, autoresizing: AutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = to_streamed_response_wrapper( + autoresizing.retrieve, + ) + self.update = to_streamed_response_wrapper( + autoresizing.update, + ) + + +class AsyncAutoresizingResourceWithStreamingResponse: + def __init__(self, autoresizing: AsyncAutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = async_to_streamed_response_wrapper( + autoresizing.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + autoresizing.update, + ) diff --git a/src/dedalus_sdk/resources/machines/executions/__init__.py b/src/dedalus_sdk/resources/machines/executions/__init__.py new file mode 100644 index 0000000..2103c6e --- /dev/null +++ b/src/dedalus_sdk/resources/machines/executions/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from .executions import ( + ExecutionsResource, + AsyncExecutionsResource, + ExecutionsResourceWithRawResponse, + AsyncExecutionsResourceWithRawResponse, + ExecutionsResourceWithStreamingResponse, + AsyncExecutionsResourceWithStreamingResponse, +) +from .logs import ( + LogsResource, + AsyncLogsResource, + LogsResourceWithRawResponse, + AsyncLogsResourceWithRawResponse, + LogsResourceWithStreamingResponse, + AsyncLogsResourceWithStreamingResponse, +) + +__all__ = [ + "ExecutionsResource", + "AsyncExecutionsResource", + "ExecutionsResourceWithRawResponse", + "AsyncExecutionsResourceWithRawResponse", + "ExecutionsResourceWithStreamingResponse", + "AsyncExecutionsResourceWithStreamingResponse", + "LogsResource", + "AsyncLogsResource", + "LogsResourceWithRawResponse", + "AsyncLogsResourceWithRawResponse", + "LogsResourceWithStreamingResponse", + "AsyncLogsResourceWithStreamingResponse", +] diff --git a/src/dedalus_sdk/resources/machines/executions.py b/src/dedalus_sdk/resources/machines/executions/executions.py similarity index 94% rename from src/dedalus_sdk/resources/machines/executions.py rename to src/dedalus_sdk/resources/machines/executions/executions.py index 4677392..6cd4a28 100644 --- a/src/dedalus_sdk/resources/machines/executions.py +++ b/src/dedalus_sdk/resources/machines/executions/executions.py @@ -5,29 +5,41 @@ import httpx from typing import Dict, Optional -from ..._types import SequenceNotStr +from ...._types import SequenceNotStr -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 ( +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 ...pagination import SyncCursorPage, AsyncCursorPage -from ..._base_client import AsyncPaginator, make_request_options -from ...types.machines import execution_list_params, execution_create_params, execution_events_params -from ...types.machines.execution import Execution -from ...types.machines.execution_output import ExecutionOutput -from ...types.machines.execution_event import ExecutionEvent +from ....pagination import SyncCursorPage, AsyncCursorPage +from ...._base_client import AsyncPaginator, make_request_options +from .logs import ( + LogsResource, + AsyncLogsResource, + LogsResourceWithRawResponse, + AsyncLogsResourceWithRawResponse, + LogsResourceWithStreamingResponse, + AsyncLogsResourceWithStreamingResponse, +) +from ....types.machines import execution_list_params, execution_create_params, execution_events_params +from ....types.machines.execution import Execution +from ....types.machines.execution_output import ExecutionOutput +from ....types.machines.execution_event import ExecutionEvent __all__ = ["ExecutionsResource", "AsyncExecutionsResource"] class ExecutionsResource(SyncAPIResource): + @cached_property + def logs(self) -> LogsResource: + return LogsResource(self._client) + @cached_property def with_raw_response(self) -> ExecutionsResourceWithRawResponse: return ExecutionsResourceWithRawResponse(self) @@ -373,6 +385,10 @@ def events( class AsyncExecutionsResource(AsyncAPIResource): + @cached_property + def logs(self) -> AsyncLogsResource: + return AsyncLogsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncExecutionsResourceWithRawResponse: return AsyncExecutionsResourceWithRawResponse(self) @@ -740,6 +756,10 @@ def __init__(self, executions: ExecutionsResource) -> None: executions.events, ) + @cached_property + def logs(self) -> LogsResourceWithRawResponse: + return LogsResourceWithRawResponse(self._executions.logs) + class AsyncExecutionsResourceWithRawResponse: def __init__(self, executions: AsyncExecutionsResource) -> None: @@ -764,6 +784,10 @@ def __init__(self, executions: AsyncExecutionsResource) -> None: executions.events, ) + @cached_property + def logs(self) -> AsyncLogsResourceWithRawResponse: + return AsyncLogsResourceWithRawResponse(self._executions.logs) + class ExecutionsResourceWithStreamingResponse: def __init__(self, executions: ExecutionsResource) -> None: @@ -788,6 +812,10 @@ def __init__(self, executions: ExecutionsResource) -> None: executions.events, ) + @cached_property + def logs(self) -> LogsResourceWithStreamingResponse: + return LogsResourceWithStreamingResponse(self._executions.logs) + class AsyncExecutionsResourceWithStreamingResponse: def __init__(self, executions: AsyncExecutionsResource) -> None: @@ -811,3 +839,7 @@ def __init__(self, executions: AsyncExecutionsResource) -> None: self.events = async_to_streamed_response_wrapper( executions.events, ) + + @cached_property + def logs(self) -> AsyncLogsResourceWithStreamingResponse: + return AsyncLogsResourceWithStreamingResponse(self._executions.logs) diff --git a/src/dedalus_sdk/resources/machines/executions/logs.py b/src/dedalus_sdk/resources/machines/executions/logs.py new file mode 100644 index 0000000..652324f --- /dev/null +++ b/src/dedalus_sdk/resources/machines/executions/logs.py @@ -0,0 +1,423 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import httpx + +from ...._types import Body, Query, Headers, NotGiven, not_given +from ...._utils import path_template +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.machines.executions.status import Status +from ....types.machines.executions.read_token import ReadToken + +__all__ = ["LogsResource", "AsyncLogsResource"] + + +class LogsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> LogsResourceWithRawResponse: + return LogsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> LogsResourceWithStreamingResponse: + return LogsResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + machine_id: str, + execution_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Status: + """ + Get execution log status + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + execution_id: Path parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Status: OK + + Example: + ```python + log = client.machines.executions.logs.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return self._get( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}/logs", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Status, + ) + + def reauthorize( + self, + *, + machine_id: str, + execution_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> Status: + """ + Reauthorize execution log publication + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + execution_id: Path parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Status: OK + + Example: + ```python + log = client.machines.executions.logs.reauthorize( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return self._post( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}/logs/reauthorize", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Status, + ) + + def create_token( + self, + *, + machine_id: str, + execution_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> ReadToken: + """ + Create execution log read token + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + execution_id: Path parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + ReadToken: OK + + Example: + ```python + log = client.machines.executions.logs.create_token( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return self._post( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}/logs/token", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ReadToken, + ) + + +class AsyncLogsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncLogsResourceWithRawResponse: + return AsyncLogsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncLogsResourceWithStreamingResponse: + return AsyncLogsResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + machine_id: str, + execution_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Status: + """ + Get execution log status + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + execution_id: Path parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Status: OK + + Example: + ```python + log = await client.machines.executions.logs.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return await self._get( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}/logs", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Status, + ) + + async def reauthorize( + self, + *, + machine_id: str, + execution_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> Status: + """ + Reauthorize execution log publication + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + execution_id: Path parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Status: OK + + Example: + ```python + log = await client.machines.executions.logs.reauthorize( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return await self._post( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}/logs/reauthorize", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Status, + ) + + async def create_token( + self, + *, + machine_id: str, + execution_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> ReadToken: + """ + Create execution log read token + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + execution_id: Path parameter. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + ReadToken: OK + + Example: + ```python + log = await client.machines.executions.logs.create_token( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + if execution_id is None or (isinstance(execution_id, str) and not execution_id): + raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}") + return await self._post( + path_template( + "/v1/machines/{machine_id}/executions/{execution_id}/logs/token", + **{"machine_id": machine_id, "execution_id": execution_id}, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=ReadToken, + ) + + +class LogsResourceWithRawResponse: + def __init__(self, logs: LogsResource) -> None: + self._logs = logs + + self.retrieve = to_raw_response_wrapper( + logs.retrieve, + ) + self.reauthorize = to_raw_response_wrapper( + logs.reauthorize, + ) + self.create_token = to_raw_response_wrapper( + logs.create_token, + ) + + +class AsyncLogsResourceWithRawResponse: + def __init__(self, logs: AsyncLogsResource) -> None: + self._logs = logs + + self.retrieve = async_to_raw_response_wrapper( + logs.retrieve, + ) + self.reauthorize = async_to_raw_response_wrapper( + logs.reauthorize, + ) + self.create_token = async_to_raw_response_wrapper( + logs.create_token, + ) + + +class LogsResourceWithStreamingResponse: + def __init__(self, logs: LogsResource) -> None: + self._logs = logs + + self.retrieve = to_streamed_response_wrapper( + logs.retrieve, + ) + self.reauthorize = to_streamed_response_wrapper( + logs.reauthorize, + ) + self.create_token = to_streamed_response_wrapper( + logs.create_token, + ) + + +class AsyncLogsResourceWithStreamingResponse: + def __init__(self, logs: AsyncLogsResource) -> None: + self._logs = logs + + self.retrieve = async_to_streamed_response_wrapper( + logs.retrieve, + ) + self.reauthorize = async_to_streamed_response_wrapper( + logs.reauthorize, + ) + self.create_token = async_to_streamed_response_wrapper( + logs.create_token, + ) diff --git a/src/dedalus_sdk/resources/machines/machines.py b/src/dedalus_sdk/resources/machines/machines.py index cf60917..a41e7a3 100644 --- a/src/dedalus_sdk/resources/machines/machines.py +++ b/src/dedalus_sdk/resources/machines/machines.py @@ -32,15 +32,15 @@ ExecutionsResourceWithStreamingResponse, AsyncExecutionsResourceWithStreamingResponse, ) -from .terminals import ( - TerminalsResource, - AsyncTerminalsResource, - TerminalsResourceWithRawResponse, - AsyncTerminalsResourceWithRawResponse, - TerminalsResourceWithStreamingResponse, - AsyncTerminalsResourceWithStreamingResponse, +from .autoresizing import ( + AutoresizingResource, + AsyncAutoresizingResource, + AutoresizingResourceWithRawResponse, + AsyncAutoresizingResourceWithRawResponse, + AutoresizingResourceWithStreamingResponse, + AsyncAutoresizingResourceWithStreamingResponse, ) -from ...types import machine_list_params, machine_create_params, machine_update_params +from ...types import machine_list_params, machine_create_params, machine_update_params, machine_reboot_params from ...types.machine_list_item import MachineListItem from ...types.machine import Machine from ...types.machine_retrieve_response import MachineRetrieveResponse @@ -58,8 +58,8 @@ def executions(self) -> ExecutionsResource: return ExecutionsResource(self._client) @cached_property - def terminals(self) -> TerminalsResource: - return TerminalsResource(self._client) + def autoresizing(self) -> AutoresizingResource: + return AutoresizingResource(self._client) @cached_property def with_raw_response(self) -> MachinesResourceWithRawResponse: @@ -428,6 +428,57 @@ def wake( cast_to=Machine, ) + def reboot( + self, + *, + machine_id: str, + force: bool | 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, + idempotency_key: str | None = None, + ) -> Machine: + """ + Checkpoints files and replaces the runtime. The machine ID and filesystem are preserved. RAM, processes, and temporary mounts are cleared. Poll the machine until its phase is running. Retry the same Idempotency-Key after a lost response. + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + force: Recover from the last committed filesystem checkpoint without guest cooperation. Unpublished file writes are lost. The default checkpoints files before rebooting. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = client.machines.reboot( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + return self._post( + path_template("/v1/machines/{machine_id}/reboot", **{"machine_id": machine_id}), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + query=maybe_transform({"force": force}, machine_reboot_params.MachineRebootParams), + ), + cast_to=Machine, + ) + class AsyncMachinesResource(AsyncAPIResource): @cached_property @@ -439,8 +490,8 @@ def executions(self) -> AsyncExecutionsResource: return AsyncExecutionsResource(self._client) @cached_property - def terminals(self) -> AsyncTerminalsResource: - return AsyncTerminalsResource(self._client) + def autoresizing(self) -> AsyncAutoresizingResource: + return AsyncAutoresizingResource(self._client) @cached_property def with_raw_response(self) -> AsyncMachinesResourceWithRawResponse: @@ -809,6 +860,57 @@ async def wake( cast_to=Machine, ) + async def reboot( + self, + *, + machine_id: str, + force: bool | 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, + idempotency_key: str | None = None, + ) -> Machine: + """ + Checkpoints files and replaces the runtime. The machine ID and filesystem are preserved. RAM, processes, and temporary mounts are cleared. Poll the machine until its phase is running. Retry the same Idempotency-Key after a lost response. + + Args: + machine_id: Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged. + force: Recover from the last committed filesystem checkpoint without guest cooperation. Unpublished file writes are lost. The default checkpoints files before rebooting. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Machine: OK + + Example: + ```python + machine = await client.machines.reboot( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + idempotency_key="", + ) + ``` + """ + if machine_id is None or (isinstance(machine_id, str) and not machine_id): + raise ValueError(f"Expected a non-empty value for `machine_id` but received {machine_id!r}") + return await self._post( + path_template("/v1/machines/{machine_id}/reboot", **{"machine_id": machine_id}), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + query=await async_maybe_transform({"force": force}, machine_reboot_params.MachineRebootParams), + ), + cast_to=Machine, + ) + class MachinesResourceWithRawResponse: def __init__(self, machines: MachinesResource) -> None: @@ -835,6 +937,9 @@ def __init__(self, machines: MachinesResource) -> None: self.wake = to_raw_response_wrapper( machines.wake, ) + self.reboot = to_raw_response_wrapper( + machines.reboot, + ) @cached_property def ssh(self) -> SSHResourceWithRawResponse: @@ -845,8 +950,8 @@ def executions(self) -> ExecutionsResourceWithRawResponse: return ExecutionsResourceWithRawResponse(self._machines.executions) @cached_property - def terminals(self) -> TerminalsResourceWithRawResponse: - return TerminalsResourceWithRawResponse(self._machines.terminals) + def autoresizing(self) -> AutoresizingResourceWithRawResponse: + return AutoresizingResourceWithRawResponse(self._machines.autoresizing) class AsyncMachinesResourceWithRawResponse: @@ -874,6 +979,9 @@ def __init__(self, machines: AsyncMachinesResource) -> None: self.wake = async_to_raw_response_wrapper( machines.wake, ) + self.reboot = async_to_raw_response_wrapper( + machines.reboot, + ) @cached_property def ssh(self) -> AsyncSSHResourceWithRawResponse: @@ -884,8 +992,8 @@ def executions(self) -> AsyncExecutionsResourceWithRawResponse: return AsyncExecutionsResourceWithRawResponse(self._machines.executions) @cached_property - def terminals(self) -> AsyncTerminalsResourceWithRawResponse: - return AsyncTerminalsResourceWithRawResponse(self._machines.terminals) + def autoresizing(self) -> AsyncAutoresizingResourceWithRawResponse: + return AsyncAutoresizingResourceWithRawResponse(self._machines.autoresizing) class MachinesResourceWithStreamingResponse: @@ -913,6 +1021,9 @@ def __init__(self, machines: MachinesResource) -> None: self.wake = to_streamed_response_wrapper( machines.wake, ) + self.reboot = to_streamed_response_wrapper( + machines.reboot, + ) @cached_property def ssh(self) -> SSHResourceWithStreamingResponse: @@ -923,8 +1034,8 @@ def executions(self) -> ExecutionsResourceWithStreamingResponse: return ExecutionsResourceWithStreamingResponse(self._machines.executions) @cached_property - def terminals(self) -> TerminalsResourceWithStreamingResponse: - return TerminalsResourceWithStreamingResponse(self._machines.terminals) + def autoresizing(self) -> AutoresizingResourceWithStreamingResponse: + return AutoresizingResourceWithStreamingResponse(self._machines.autoresizing) class AsyncMachinesResourceWithStreamingResponse: @@ -952,6 +1063,9 @@ def __init__(self, machines: AsyncMachinesResource) -> None: self.wake = async_to_streamed_response_wrapper( machines.wake, ) + self.reboot = async_to_streamed_response_wrapper( + machines.reboot, + ) @cached_property def ssh(self) -> AsyncSSHResourceWithStreamingResponse: @@ -962,5 +1076,5 @@ def executions(self) -> AsyncExecutionsResourceWithStreamingResponse: return AsyncExecutionsResourceWithStreamingResponse(self._machines.executions) @cached_property - def terminals(self) -> AsyncTerminalsResourceWithStreamingResponse: - return AsyncTerminalsResourceWithStreamingResponse(self._machines.terminals) + def autoresizing(self) -> AsyncAutoresizingResourceWithStreamingResponse: + return AsyncAutoresizingResourceWithStreamingResponse(self._machines.autoresizing) diff --git a/src/dedalus_sdk/resources/machines/terminals/__init__.py b/src/dedalus_sdk/resources/machines/terminals/__init__.py deleted file mode 100644 index 94e2e99..0000000 --- a/src/dedalus_sdk/resources/machines/terminals/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from .terminals import ( - TerminalsResource, - AsyncTerminalsResource, - TerminalsResourceWithRawResponse, - AsyncTerminalsResourceWithRawResponse, - TerminalsResourceWithStreamingResponse, - AsyncTerminalsResourceWithStreamingResponse, - TerminalsResourceConnectionManager, - AsyncTerminalsResourceConnectionManager, - TerminalsResourceConnection, - AsyncTerminalsResourceConnection, -) - -__all__ = [ - "TerminalsResource", - "AsyncTerminalsResource", - "TerminalsResourceWithRawResponse", - "AsyncTerminalsResourceWithRawResponse", - "TerminalsResourceWithStreamingResponse", - "AsyncTerminalsResourceWithStreamingResponse", - "TerminalsResourceConnectionManager", - "AsyncTerminalsResourceConnectionManager", - "TerminalsResourceConnection", - "AsyncTerminalsResourceConnection", -] diff --git a/src/dedalus_sdk/resources/machines/terminals/terminals.py b/src/dedalus_sdk/resources/machines/terminals/terminals.py deleted file mode 100644 index 671fdfb..0000000 --- a/src/dedalus_sdk/resources/machines/terminals/terminals.py +++ /dev/null @@ -1,124 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -import httpx - -from typing import Callable - -from ...._types import Query, Headers -from ...._compat import cached_property -from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...._base_client import make_request_options -from ....types.websocket_connection_options import WebSocketConnectionOptions -from ....types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides -from .ws import ( - TerminalsResourceConnectionManager as TerminalsResourceConnectionManager, - AsyncTerminalsResourceConnectionManager as AsyncTerminalsResourceConnectionManager, - TerminalsResourceConnection as TerminalsResourceConnection, - AsyncTerminalsResourceConnection as AsyncTerminalsResourceConnection, -) - -__all__ = ["TerminalsResource", "AsyncTerminalsResource"] - - -class TerminalsResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> TerminalsResourceWithRawResponse: - return TerminalsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> TerminalsResourceWithStreamingResponse: - return TerminalsResourceWithStreamingResponse(self) - - def connect( - self, - *, - machine_id: str, - terminal_id: str, - extra_query: Query = {}, - extra_headers: Headers = {}, - websocket_connection_options: WebSocketConnectionOptions = {}, - on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, - max_retries: int = 5, - initial_delay: float = 0.5, - max_delay: float = 8.0, - max_queue_size: int = 1_048_576, - ) -> TerminalsResourceConnectionManager: - return TerminalsResourceConnectionManager( - client=self._client, - machine_id=machine_id, - terminal_id=terminal_id, - extra_query=extra_query, - extra_headers=extra_headers, - websocket_connection_options=websocket_connection_options, - on_reconnecting=on_reconnecting, - max_retries=max_retries, - initial_delay=initial_delay, - max_delay=max_delay, - max_queue_size=max_queue_size, - ) - - -class AsyncTerminalsResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncTerminalsResourceWithRawResponse: - return AsyncTerminalsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncTerminalsResourceWithStreamingResponse: - return AsyncTerminalsResourceWithStreamingResponse(self) - - def connect( - self, - *, - machine_id: str, - terminal_id: str, - extra_query: Query = {}, - extra_headers: Headers = {}, - websocket_connection_options: WebSocketConnectionOptions = {}, - on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, - max_retries: int = 5, - initial_delay: float = 0.5, - max_delay: float = 8.0, - max_queue_size: int = 1_048_576, - ) -> AsyncTerminalsResourceConnectionManager: - return AsyncTerminalsResourceConnectionManager( - client=self._client, - machine_id=machine_id, - terminal_id=terminal_id, - extra_query=extra_query, - extra_headers=extra_headers, - websocket_connection_options=websocket_connection_options, - on_reconnecting=on_reconnecting, - max_retries=max_retries, - initial_delay=initial_delay, - max_delay=max_delay, - max_queue_size=max_queue_size, - ) - - -class TerminalsResourceWithRawResponse: - def __init__(self, terminals: TerminalsResource) -> None: - self._terminals = terminals - - -class AsyncTerminalsResourceWithRawResponse: - def __init__(self, terminals: AsyncTerminalsResource) -> None: - self._terminals = terminals - - -class TerminalsResourceWithStreamingResponse: - def __init__(self, terminals: TerminalsResource) -> None: - self._terminals = terminals - - -class AsyncTerminalsResourceWithStreamingResponse: - def __init__(self, terminals: AsyncTerminalsResource) -> None: - self._terminals = terminals diff --git a/src/dedalus_sdk/resources/machines/terminals/ws.py b/src/dedalus_sdk/resources/machines/terminals/ws.py deleted file mode 100644 index f92dd94..0000000 --- a/src/dedalus_sdk/resources/machines/terminals/ws.py +++ /dev/null @@ -1,782 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -import json -import time -import random -import logging -from types import TracebackType -from typing import TYPE_CHECKING, Any, Union, Callable, Awaitable, Iterator, cast -from typing_extensions import AsyncIterator - -import httpx - -from ...._models import BaseModel, construct_type_unchecked -from ...._types import Headers, Query -from ...._exceptions import DedalusError, WebSocketConnectionClosedError -from ...._send_queue import SendQueue -from ...._base_client import _merge_mappings -from ...._event_handler import EventHandlerRegistry -from ...._utils import path_template, maybe_transform, async_maybe_transform -from ....types.websocket_connection_options import WebSocketConnectionOptions -from ....types.websocket_reconnection import ReconnectingEvent, ReconnectingOverrides, is_recoverable_close -from ....types.machines.connect_client_event import ConnectClientEvent -from ....types.machines.connect_client_event_param import ConnectClientEventParam -from ....types.machines.connect_server_event import ConnectServerEvent - -if TYPE_CHECKING: - from websockets.sync.client import ClientConnection as WebSocketConnection - from websockets.asyncio.client import ClientConnection as AsyncWebSocketConnection - from ...._client import Dedalus, AsyncDedalus - -__all__ = [ - "TerminalsResourceConnectionManager", - "AsyncTerminalsResourceConnectionManager", - "TerminalsResourceConnection", - "AsyncTerminalsResourceConnection", -] - -log: logging.Logger = logging.getLogger(__name__) - - -def _cookie_header(cookies: dict[str, str]) -> Headers: - """Serialize auth cookies into the WebSocket upgrade headers.""" - if not cookies: - return {} - - return {"Cookie": "; ".join(f"{key}={value}" for key, value in cookies.items())} - - -class TerminalsResourceConnection: - """Represents a live synchronous WebSocket connection.""" - - def __init__( - self, - connection: WebSocketConnection, - *, - make_ws: Callable[[Query, Headers], WebSocketConnection] | None = None, - on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, - max_retries: int = 5, - initial_delay: float = 0.5, - max_delay: float = 8.0, - extra_query: Query = {}, - extra_headers: Headers = {}, - send_queue: SendQueue | None = None, - ) -> None: - self._connection = connection - self._make_ws = make_ws - self._on_reconnecting = on_reconnecting - self._max_retries = max_retries - self._initial_delay = initial_delay - self._max_delay = max_delay - self._extra_query = extra_query - self._extra_headers = extra_headers - self._intentionally_closed = False - self._is_reconnecting = False - self._send_queue = send_queue or SendQueue() - self._event_handler_registry = EventHandlerRegistry(use_lock=True) - - def __iter__(self) -> Iterator[ConnectServerEvent]: - """Yield events until the connection closes.""" - from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError - - while True: - try: - yield self.recv() - except ConnectionClosedOK: - return - except ConnectionClosedError as exc: - if not self._reconnect(exc): - unsent = self._send_queue.drain() - if unsent: - raise WebSocketConnectionClosedError( - "WebSocket connection closed with unsent messages", - unsent_messages=unsent, - ) from exc - raise - - def recv(self) -> ConnectServerEvent: - """Receive and parse the next websocket message.""" - return self.parse_event(self.recv_bytes()) - - def recv_bytes(self) -> bytes: - """Receive the next websocket message as raw bytes.""" - message = self._connection.recv(decode=False) - log.debug("Received WebSocket message: %s", message) - return message - - def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: - data = ( - event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) - if isinstance(event, BaseModel) - else json.dumps(maybe_transform(event, ConnectClientEventParam)) - ) - if self._is_reconnecting: - self._send_queue.enqueue(data) - return - try: - self._connection.send(data) - except Exception: - self._send_queue.enqueue(data) - raise - - def send_raw(self, data: bytes | str) -> None: - if self._is_reconnecting: - raw = data if isinstance(data, str) else data.decode("utf-8") - self._send_queue.enqueue(raw) - return - self._connection.send(data) - - def close(self, *, code: int = 1000, reason: str = "") -> None: - self._intentionally_closed = True - self._connection.close(code=code, reason=reason) - - def parse_event(self, data: str | bytes) -> ConnectServerEvent: - """Convert a raw websocket message into the generated server event type.""" - return cast( - ConnectServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, ConnectServerEvent)) - ) - - def _reconnect(self, exc: Exception) -> bool: - """Attempt to reconnect after a recoverable close exception.""" - if self._on_reconnecting is None or self._make_ws is None: - return False - - from websockets.exceptions import ConnectionClosedError - - close_code = 1006 - if isinstance(exc, ConnectionClosedError) and exc.rcvd is not None: - close_code = exc.rcvd.code - - if not is_recoverable_close(close_code): - return False - - self._is_reconnecting = True - for attempt in range(1, self._max_retries + 1): - base_delay = min(self._initial_delay * (2 ** (attempt - 1)), self._max_delay) - jitter = 0.75 + random.random() * 0.25 - delay = base_delay * jitter - - event = ReconnectingEvent( - attempt=attempt, - max_attempts=self._max_retries, - delay=delay, - close_code=close_code, - extra_query=self._extra_query, - extra_headers=self._extra_headers, - ) - try: - overrides = self._on_reconnecting(event) - except Exception: - self._is_reconnecting = False - return False - if overrides is not None and overrides.get("abort"): - self._is_reconnecting = False - return False - if overrides is not None: - if "extra_query" in overrides: - self._extra_query = overrides["extra_query"] - if "extra_headers" in overrides: - self._extra_headers = overrides["extra_headers"] - log.info( - "Reconnecting to WebSocket API (attempt %d/%d) after %.1fs delay", - attempt, - self._max_retries, - delay, - ) - time.sleep(delay) - if self._intentionally_closed: - self._is_reconnecting = False - return False - try: - self._connection = self._make_ws(self._extra_query, self._extra_headers) - log.info("Reconnected to WebSocket API") - self._flush_send_queue() - self._is_reconnecting = False - return True - except Exception: - pass - self._is_reconnecting = False - return False - - def _flush_send_queue(self) -> None: - """Send queued messages over the current connection after it opens or reconnects.""" - self._send_queue.flush_sync(lambda data: self._connection.send(data)) - - def on( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[TerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register an event handler, or return a decorator that registers one.""" - if handler is not None: - self._event_handler_registry.add(event_type, handler) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self._event_handler_registry.add(event_type, fn) - return fn - - return decorator - - def off(self, event_type: str, handler: Callable[..., Any]) -> TerminalsResourceConnection: - """Remove a previously registered event handler.""" - self._event_handler_registry.remove(event_type, handler) - return self - - def once( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[TerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register a one-time event handler.""" - if handler is not None: - self._event_handler_registry.add(event_type, handler, once=True) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self._event_handler_registry.add(event_type, fn, once=True) - return fn - - return decorator - - def dispatch_events(self) -> None: - """Dispatch incoming events to registered handlers until the connection closes.""" - for event in self: - event_type = event.type - specific = self._event_handler_registry.get_handlers(event_type) - generic = self._event_handler_registry.get_handlers("event") - - for handler in specific: - handler(event) - - for handler in generic: - handler(event) - - -class AsyncTerminalsResourceConnection: - """Represents a live asynchronous WebSocket connection.""" - - def __init__( - self, - connection: AsyncWebSocketConnection, - *, - make_ws: Callable[[Query, Headers], Awaitable[AsyncWebSocketConnection]] | None = None, - on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, - max_retries: int = 5, - initial_delay: float = 0.5, - max_delay: float = 8.0, - extra_query: Query = {}, - extra_headers: Headers = {}, - send_queue: SendQueue | None = None, - ) -> None: - self._connection = connection - self._make_ws = make_ws - self._on_reconnecting = on_reconnecting - self._max_retries = max_retries - self._initial_delay = initial_delay - self._max_delay = max_delay - self._extra_query = extra_query - self._extra_headers = extra_headers - self._intentionally_closed = False - self._is_reconnecting = False - self._send_queue = send_queue or SendQueue() - self._event_handler_registry = EventHandlerRegistry(use_lock=False) - - async def __aiter__(self) -> AsyncIterator[ConnectServerEvent]: - """Yield events until the connection closes.""" - from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError - - while True: - try: - yield await self.recv() - except ConnectionClosedOK: - return - except ConnectionClosedError as exc: - if not await self._reconnect(exc): - unsent = self._send_queue.drain() - if unsent: - raise WebSocketConnectionClosedError( - "WebSocket connection closed with unsent messages", - unsent_messages=unsent, - ) from exc - raise - - async def recv(self) -> ConnectServerEvent: - """Receive and parse the next websocket message.""" - return self.parse_event(await self.recv_bytes()) - - async def recv_bytes(self) -> bytes: - """Receive the next websocket message as raw bytes.""" - message = await self._connection.recv(decode=False) - log.debug("Received WebSocket message: %s", message) - return message - - async def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: - data = ( - event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) - if isinstance(event, BaseModel) - else json.dumps(await async_maybe_transform(event, ConnectClientEventParam)) - ) - if self._is_reconnecting: - self._send_queue.enqueue(data) - return - try: - await self._connection.send(data) - except Exception: - self._send_queue.enqueue(data) - raise - - async def send_raw(self, data: bytes | str) -> None: - if self._is_reconnecting: - raw = data if isinstance(data, str) else data.decode("utf-8") - self._send_queue.enqueue(raw) - return - await self._connection.send(data) - - async def close(self, *, code: int = 1000, reason: str = "") -> None: - self._intentionally_closed = True - await self._connection.close(code=code, reason=reason) - - def parse_event(self, data: str | bytes) -> ConnectServerEvent: - """Convert a raw websocket message into the generated server event type.""" - return cast( - ConnectServerEvent, construct_type_unchecked(value=json.loads(data), type_=cast(Any, ConnectServerEvent)) - ) - - async def _reconnect(self, exc: Exception) -> bool: - """Attempt to reconnect after a recoverable close exception.""" - import asyncio - - if self._on_reconnecting is None or self._make_ws is None: - return False - - from websockets.exceptions import ConnectionClosedError - - close_code = 1006 - if isinstance(exc, ConnectionClosedError) and exc.rcvd is not None: - close_code = exc.rcvd.code - - if not is_recoverable_close(close_code): - return False - - self._is_reconnecting = True - for attempt in range(1, self._max_retries + 1): - base_delay = min(self._initial_delay * (2 ** (attempt - 1)), self._max_delay) - jitter = 0.75 + random.random() * 0.25 - delay = base_delay * jitter - - event = ReconnectingEvent( - attempt=attempt, - max_attempts=self._max_retries, - delay=delay, - close_code=close_code, - extra_query=self._extra_query, - extra_headers=self._extra_headers, - ) - try: - overrides = self._on_reconnecting(event) - except Exception: - self._is_reconnecting = False - return False - if overrides is not None and overrides.get("abort"): - self._is_reconnecting = False - return False - if overrides is not None: - if "extra_query" in overrides: - self._extra_query = overrides["extra_query"] - if "extra_headers" in overrides: - self._extra_headers = overrides["extra_headers"] - log.info( - "Reconnecting to WebSocket API (attempt %d/%d) after %.1fs delay", - attempt, - self._max_retries, - delay, - ) - await asyncio.sleep(delay) - if self._intentionally_closed: - self._is_reconnecting = False - return False - try: - self._connection = await self._make_ws(self._extra_query, self._extra_headers) - log.info("Reconnected to WebSocket API") - await self._flush_send_queue() - self._is_reconnecting = False - return True - except Exception: - pass - self._is_reconnecting = False - return False - - async def _flush_send_queue(self) -> None: - """Send queued messages over the current connection after it opens or reconnects.""" - - async def _send(data: str) -> None: - await self._connection.send(data) - - await self._send_queue.flush_async(_send) - - def on( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[AsyncTerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register an event handler, or return a decorator that registers one.""" - if handler is not None: - self._event_handler_registry.add(event_type, handler) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self._event_handler_registry.add(event_type, fn) - return fn - - return decorator - - def off(self, event_type: str, handler: Callable[..., Any]) -> AsyncTerminalsResourceConnection: - """Remove a previously registered event handler.""" - self._event_handler_registry.remove(event_type, handler) - return self - - def once( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[AsyncTerminalsResourceConnection, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register a one-time event handler.""" - if handler is not None: - self._event_handler_registry.add(event_type, handler, once=True) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self._event_handler_registry.add(event_type, fn, once=True) - return fn - - return decorator - - async def dispatch_events(self) -> None: - """Dispatch incoming events to registered handlers until the connection closes.""" - import asyncio - - async for event in self: - event_type = event.type - specific = self._event_handler_registry.get_handlers(event_type) - generic = self._event_handler_registry.get_handlers("event") - - for handler in specific: - result = handler(event) - if asyncio.iscoroutine(result): - await result - - for handler in generic: - result = handler(event) - if asyncio.iscoroutine(result): - await result - - -class TerminalsResourceConnectionManager: - """Context-manager wrapper used by `connect()` to open a websocket lifecycle.""" - - def __init__( - self, - *, - client: Dedalus, - machine_id: str, - terminal_id: str, - extra_query: Query, - extra_headers: Headers, - websocket_connection_options: WebSocketConnectionOptions, - on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, - max_retries: int = 5, - initial_delay: float = 0.5, - max_delay: float = 8.0, - max_queue_size: int = 1_048_576, - ) -> None: - self.__client = client - self.__machine_id = machine_id - self.__terminal_id = terminal_id - self.__connection: TerminalsResourceConnection | None = None - self.__extra_query = extra_query - self.__extra_headers = extra_headers - self.__websocket_connection_options = websocket_connection_options - self.__on_reconnecting = on_reconnecting - self.__max_retries = max_retries - self.__initial_delay = initial_delay - self.__max_delay = max_delay - self.__send_queue = SendQueue(max_bytes=max_queue_size) - self.__event_handler_registry = EventHandlerRegistry(use_lock=True) - - def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: - """Queue a message to send as soon as the websocket opens.""" - data = ( - event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) - if isinstance(event, BaseModel) - else json.dumps(maybe_transform(event, ConnectClientEventParam)) - ) - self.__send_queue.enqueue(data) - - def on( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[TerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register an event handler before the connection opens.""" - if handler is not None: - self.__event_handler_registry.add(event_type, handler) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self.__event_handler_registry.add(event_type, fn) - return fn - - return decorator - - def off(self, event_type: str, handler: Callable[..., Any]) -> TerminalsResourceConnectionManager: - """Remove a previously registered event handler.""" - self.__event_handler_registry.remove(event_type, handler) - return self - - def once( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[TerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register a one-time event handler before the connection opens.""" - if handler is not None: - self.__event_handler_registry.add(event_type, handler, once=True) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self.__event_handler_registry.add(event_type, fn, once=True) - return fn - - return decorator - - def __enter__(self) -> TerminalsResourceConnection: - ws = self._connect_ws(self.__extra_query, self.__extra_headers) - - self.__connection = TerminalsResourceConnection( - ws, - make_ws=self._connect_ws if self.__on_reconnecting is not None else None, - on_reconnecting=self.__on_reconnecting, - max_retries=self.__max_retries, - initial_delay=self.__initial_delay, - max_delay=self.__max_delay, - extra_query=self.__extra_query, - extra_headers=self.__extra_headers, - send_queue=self.__send_queue, - ) - - self.__event_handler_registry.merge_into(self.__connection._event_handler_registry) - self.__connection._flush_send_queue() - - return self.__connection - - enter = __enter__ - - def _connect_ws(self, extra_query: Query, extra_headers: Headers) -> WebSocketConnection: - try: - from websockets.sync.client import connect - except ImportError as exc: - raise DedalusError("You need to install `dedalus[websockets]` to use this method") from exc - - if not self.__machine_id: - raise ValueError(f"Expected a non-empty value for `machine_id` but received {self.__machine_id!r}") - if not self.__terminal_id: - raise ValueError(f"Expected a non-empty value for `terminal_id` but received {self.__terminal_id!r}") - url = self._prepare_url() - params = _merge_mappings( - { - **url.params, - **self.__client._auth_query({}), - **self.__client.default_query, - }, - extra_query, - ) - cookies = self.__client._auth_cookies({}) - headers = _merge_mappings( - { - **self.__client.auth_headers, - **_cookie_header(cookies), - }, - extra_headers, - ) - self.__client._validate_headers(headers, extra_headers, params, cookies) - url = url.copy_with(params=params) - log.debug("Connecting to %s", url) - if self.__websocket_connection_options: - log.debug("Connection options: %s", self.__websocket_connection_options) - - return connect( - str(url), - user_agent_header=self.__client.user_agent, - additional_headers=headers, - **self.__websocket_connection_options, - ) - - def _prepare_url(self) -> httpx.URL: - if self.__client.websocket_base_url is not None: - base_url = httpx.URL(self.__client.websocket_base_url) - else: - scheme = self.__client._base_url.scheme - ws_scheme = "ws" if scheme == "http" else "wss" - base_url = self.__client._base_url.copy_with(scheme=ws_scheme) - - merge_raw_path = base_url.raw_path.rstrip(b"/") + path_template( - "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", - machine_id=self.__machine_id, - terminal_id=self.__terminal_id, - ).encode("utf-8") - return base_url.copy_with(raw_path=merge_raw_path) - - def __exit__( - self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None - ) -> None: - if self.__connection is not None: - self.__connection.close() - - -class AsyncTerminalsResourceConnectionManager: - """Async context-manager wrapper used by `connect()` to open a websocket lifecycle.""" - - def __init__( - self, - *, - client: AsyncDedalus, - machine_id: str, - terminal_id: str, - extra_query: Query, - extra_headers: Headers, - websocket_connection_options: WebSocketConnectionOptions, - on_reconnecting: Callable[[ReconnectingEvent], ReconnectingOverrides | None] | None = None, - max_retries: int = 5, - initial_delay: float = 0.5, - max_delay: float = 8.0, - max_queue_size: int = 1_048_576, - ) -> None: - self.__client = client - self.__machine_id = machine_id - self.__terminal_id = terminal_id - self.__connection: AsyncTerminalsResourceConnection | None = None - self.__extra_query = extra_query - self.__extra_headers = extra_headers - self.__websocket_connection_options = websocket_connection_options - self.__on_reconnecting = on_reconnecting - self.__max_retries = max_retries - self.__initial_delay = initial_delay - self.__max_delay = max_delay - self.__send_queue = SendQueue(max_bytes=max_queue_size) - self.__event_handler_registry = EventHandlerRegistry(use_lock=False) - - def send(self, event: ConnectClientEvent | ConnectClientEventParam) -> None: - """Queue a message to send as soon as the websocket opens.""" - data = ( - event.to_json(use_api_names=True, exclude_defaults=True, exclude_unset=True) - if isinstance(event, BaseModel) - else json.dumps(maybe_transform(event, ConnectClientEventParam)) - ) - self.__send_queue.enqueue(data) - - def on( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[AsyncTerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register an event handler before the connection opens.""" - if handler is not None: - self.__event_handler_registry.add(event_type, handler) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self.__event_handler_registry.add(event_type, fn) - return fn - - return decorator - - def off(self, event_type: str, handler: Callable[..., Any]) -> AsyncTerminalsResourceConnectionManager: - """Remove a previously registered event handler.""" - self.__event_handler_registry.remove(event_type, handler) - return self - - def once( - self, event_type: str, handler: Callable[..., Any] | None = None - ) -> Union[AsyncTerminalsResourceConnectionManager, Callable[[Callable[..., Any]], Callable[..., Any]]]: - """Register a one-time event handler before the connection opens.""" - if handler is not None: - self.__event_handler_registry.add(event_type, handler, once=True) - return self - - def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: - self.__event_handler_registry.add(event_type, fn, once=True) - return fn - - return decorator - - async def __aenter__(self) -> AsyncTerminalsResourceConnection: - ws = await self._connect_ws(self.__extra_query, self.__extra_headers) - - self.__connection = AsyncTerminalsResourceConnection( - ws, - make_ws=self._connect_ws if self.__on_reconnecting is not None else None, - on_reconnecting=self.__on_reconnecting, - max_retries=self.__max_retries, - initial_delay=self.__initial_delay, - max_delay=self.__max_delay, - extra_query=self.__extra_query, - extra_headers=self.__extra_headers, - send_queue=self.__send_queue, - ) - - self.__event_handler_registry.merge_into(self.__connection._event_handler_registry) - await self.__connection._flush_send_queue() - - return self.__connection - - enter = __aenter__ - - async def _connect_ws(self, extra_query: Query, extra_headers: Headers) -> AsyncWebSocketConnection: - try: - from websockets.asyncio.client import connect - except ImportError as exc: - raise DedalusError("You need to install `dedalus[websockets]` to use this method") from exc - - if not self.__machine_id: - raise ValueError(f"Expected a non-empty value for `machine_id` but received {self.__machine_id!r}") - if not self.__terminal_id: - raise ValueError(f"Expected a non-empty value for `terminal_id` but received {self.__terminal_id!r}") - url = self._prepare_url() - params = _merge_mappings( - { - **url.params, - **self.__client._auth_query({}), - **self.__client.default_query, - }, - extra_query, - ) - cookies = self.__client._auth_cookies({}) - headers = _merge_mappings( - { - **self.__client.auth_headers, - **_cookie_header(cookies), - }, - extra_headers, - ) - self.__client._validate_headers(headers, extra_headers, params, cookies) - url = url.copy_with(params=params) - log.debug("Connecting to %s", url) - if self.__websocket_connection_options: - log.debug("Connection options: %s", self.__websocket_connection_options) - - return await connect( - str(url), - user_agent_header=self.__client.user_agent, - additional_headers=headers, - **self.__websocket_connection_options, - ) - - def _prepare_url(self) -> httpx.URL: - if self.__client.websocket_base_url is not None: - base_url = httpx.URL(self.__client.websocket_base_url) - else: - scheme = self.__client._base_url.scheme - ws_scheme = "ws" if scheme == "http" else "wss" - base_url = self.__client._base_url.copy_with(scheme=ws_scheme) - - merge_raw_path = base_url.raw_path.rstrip(b"/") + path_template( - "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", - machine_id=self.__machine_id, - terminal_id=self.__terminal_id, - ).encode("utf-8") - return base_url.copy_with(raw_path=merge_raw_path) - - async def __aexit__( - self, exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None - ) -> None: - if self.__connection is not None: - await self.__connection.close() diff --git a/src/dedalus_sdk/resources/organization/__init__.py b/src/dedalus_sdk/resources/organization/__init__.py new file mode 100644 index 0000000..cbf2f4d --- /dev/null +++ b/src/dedalus_sdk/resources/organization/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from .organization import ( + OrganizationResource, + AsyncOrganizationResource, + OrganizationResourceWithRawResponse, + AsyncOrganizationResourceWithRawResponse, + OrganizationResourceWithStreamingResponse, + AsyncOrganizationResourceWithStreamingResponse, +) +from .autoresizing import ( + AutoresizingResource, + AsyncAutoresizingResource, + AutoresizingResourceWithRawResponse, + AsyncAutoresizingResourceWithRawResponse, + AutoresizingResourceWithStreamingResponse, + AsyncAutoresizingResourceWithStreamingResponse, +) + +__all__ = [ + "OrganizationResource", + "AsyncOrganizationResource", + "OrganizationResourceWithRawResponse", + "AsyncOrganizationResourceWithRawResponse", + "OrganizationResourceWithStreamingResponse", + "AsyncOrganizationResourceWithStreamingResponse", + "AutoresizingResource", + "AsyncAutoresizingResource", + "AutoresizingResourceWithRawResponse", + "AsyncAutoresizingResourceWithRawResponse", + "AutoresizingResourceWithStreamingResponse", + "AsyncAutoresizingResourceWithStreamingResponse", +] diff --git a/src/dedalus_sdk/resources/organization/autoresizing.py b/src/dedalus_sdk/resources/organization/autoresizing.py new file mode 100644 index 0000000..e1b1f85 --- /dev/null +++ b/src/dedalus_sdk/resources/organization/autoresizing.py @@ -0,0 +1,259 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.organization.policy import Policy +from ...types.organization import autoresizing_update_params + +__all__ = ["AutoresizingResource", "AsyncAutoresizingResource"] + + +class AutoresizingResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> AutoresizingResourceWithRawResponse: + return AutoresizingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AutoresizingResourceWithStreamingResponse: + return AutoresizingResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Policy: + """ + Read organization RAM autoresizing policy + + Args: + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Policy: OK + + Example: + ```python + autoresizing = client.organization.autoresizing.retrieve() + ``` + """ + return self._get( + "/v1/organization/autoresizing", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Policy, + ) + + def update( + self, + *, + enabled: bool, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> Policy: + """ + Set organization RAM autoresizing policy + + Args: + enabled: Allow automatic RAM increases for all organization machines. Disabling preserves applied RAM and already admitted resizes. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Policy: OK + + Example: + ```python + autoresizing = client.organization.autoresizing.update( + enabled=False, + idempotency_key="", + ) + ``` + """ + return self._put( + "/v1/organization/autoresizing", + body=maybe_transform( + {"enabled": enabled}, + autoresizing_update_params.AutoresizingUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Policy, + ) + + +class AsyncAutoresizingResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncAutoresizingResourceWithRawResponse: + return AsyncAutoresizingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAutoresizingResourceWithStreamingResponse: + return AsyncAutoresizingResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Policy: + """ + Read organization RAM autoresizing policy + + Args: + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + + Returns: + Policy: OK + + Example: + ```python + autoresizing = await client.organization.autoresizing.retrieve() + ``` + """ + return await self._get( + "/v1/organization/autoresizing", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Policy, + ) + + async def update( + self, + *, + enabled: bool, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + idempotency_key: str | None = None, + ) -> Policy: + """ + Set organization RAM autoresizing policy + + Args: + enabled: Allow automatic RAM increases for all organization machines. Disabling preserves applied RAM and already admitted resizes. + extra_headers: Send extra headers with the request. + extra_query: Send extra query parameters with the request. + extra_body: Send extra JSON properties with the request. + timeout: Override the client-level default timeout for this request, in seconds. + idempotency_key: Override or provide the idempotency key for this request. + + Returns: + Policy: OK + + Example: + ```python + autoresizing = await client.organization.autoresizing.update( + enabled=False, + idempotency_key="", + ) + ``` + """ + return await self._put( + "/v1/organization/autoresizing", + body=await async_maybe_transform( + {"enabled": enabled}, + autoresizing_update_params.AutoresizingUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + idempotency_key=idempotency_key, + ), + cast_to=Policy, + ) + + +class AutoresizingResourceWithRawResponse: + def __init__(self, autoresizing: AutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = to_raw_response_wrapper( + autoresizing.retrieve, + ) + self.update = to_raw_response_wrapper( + autoresizing.update, + ) + + +class AsyncAutoresizingResourceWithRawResponse: + def __init__(self, autoresizing: AsyncAutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = async_to_raw_response_wrapper( + autoresizing.retrieve, + ) + self.update = async_to_raw_response_wrapper( + autoresizing.update, + ) + + +class AutoresizingResourceWithStreamingResponse: + def __init__(self, autoresizing: AutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = to_streamed_response_wrapper( + autoresizing.retrieve, + ) + self.update = to_streamed_response_wrapper( + autoresizing.update, + ) + + +class AsyncAutoresizingResourceWithStreamingResponse: + def __init__(self, autoresizing: AsyncAutoresizingResource) -> None: + self._autoresizing = autoresizing + + self.retrieve = async_to_streamed_response_wrapper( + autoresizing.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + autoresizing.update, + ) diff --git a/src/dedalus_sdk/resources/organization/organization.py b/src/dedalus_sdk/resources/organization/organization.py new file mode 100644 index 0000000..e3f870b --- /dev/null +++ b/src/dedalus_sdk/resources/organization/organization.py @@ -0,0 +1,89 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +import httpx + +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from .autoresizing import ( + AutoresizingResource, + AsyncAutoresizingResource, + AutoresizingResourceWithRawResponse, + AsyncAutoresizingResourceWithRawResponse, + AutoresizingResourceWithStreamingResponse, + AsyncAutoresizingResourceWithStreamingResponse, +) + +__all__ = ["OrganizationResource", "AsyncOrganizationResource"] + + +class OrganizationResource(SyncAPIResource): + @cached_property + def autoresizing(self) -> AutoresizingResource: + return AutoresizingResource(self._client) + + @cached_property + def with_raw_response(self) -> OrganizationResourceWithRawResponse: + return OrganizationResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> OrganizationResourceWithStreamingResponse: + return OrganizationResourceWithStreamingResponse(self) + + +class AsyncOrganizationResource(AsyncAPIResource): + @cached_property + def autoresizing(self) -> AsyncAutoresizingResource: + return AsyncAutoresizingResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncOrganizationResourceWithRawResponse: + return AsyncOrganizationResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncOrganizationResourceWithStreamingResponse: + return AsyncOrganizationResourceWithStreamingResponse(self) + + +class OrganizationResourceWithRawResponse: + def __init__(self, organization: OrganizationResource) -> None: + self._organization = organization + + @cached_property + def autoresizing(self) -> AutoresizingResourceWithRawResponse: + return AutoresizingResourceWithRawResponse(self._organization.autoresizing) + + +class AsyncOrganizationResourceWithRawResponse: + def __init__(self, organization: AsyncOrganizationResource) -> None: + self._organization = organization + + @cached_property + def autoresizing(self) -> AsyncAutoresizingResourceWithRawResponse: + return AsyncAutoresizingResourceWithRawResponse(self._organization.autoresizing) + + +class OrganizationResourceWithStreamingResponse: + def __init__(self, organization: OrganizationResource) -> None: + self._organization = organization + + @cached_property + def autoresizing(self) -> AutoresizingResourceWithStreamingResponse: + return AutoresizingResourceWithStreamingResponse(self._organization.autoresizing) + + +class AsyncOrganizationResourceWithStreamingResponse: + def __init__(self, organization: AsyncOrganizationResource) -> None: + self._organization = organization + + @cached_property + def autoresizing(self) -> AsyncAutoresizingResourceWithStreamingResponse: + return AsyncAutoresizingResourceWithStreamingResponse(self._organization.autoresizing) diff --git a/src/dedalus_sdk/types/__init__.py b/src/dedalus_sdk/types/__init__.py index 462bf73..ba5db4d 100644 --- a/src/dedalus_sdk/types/__init__.py +++ b/src/dedalus_sdk/types/__init__.py @@ -10,8 +10,4 @@ from .machine_create_params import MachineCreateParams as MachineCreateParams from .machine_retrieve_response import MachineRetrieveResponse as MachineRetrieveResponse from .machine_update_params import MachineUpdateParams as MachineUpdateParams -from .websocket_connection_options import WebSocketConnectionOptions as WebSocketConnectionOptions -from .websocket_reconnection import ( - ReconnectingEvent as ReconnectingEvent, - ReconnectingOverrides as ReconnectingOverrides, -) +from .machine_reboot_params import MachineRebootParams as MachineRebootParams diff --git a/src/dedalus_sdk/types/machine_reboot_params.py b/src/dedalus_sdk/types/machine_reboot_params.py new file mode 100644 index 0000000..131190e --- /dev/null +++ b/src/dedalus_sdk/types/machine_reboot_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["MachineRebootParams"] + + +class MachineRebootParams(TypedDict, total=False): + machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" + + force: bool + """Recover from the last committed filesystem checkpoint without guest cooperation. Unpublished file writes are lost. The default checkpoints files before rebooting.""" diff --git a/src/dedalus_sdk/types/machines/__init__.py b/src/dedalus_sdk/types/machines/__init__.py index dbe964f..6e62e9d 100644 --- a/src/dedalus_sdk/types/machines/__init__.py +++ b/src/dedalus_sdk/types/machines/__init__.py @@ -8,6 +8,7 @@ from .execution_list import ExecutionList as ExecutionList from .execution_output import ExecutionOutput as ExecutionOutput from .execution import Execution as Execution +from .settings import Settings as Settings from .ssh_connection import SSHConnection as SSHConnection from .ssh_host_trust import SSHHostTrust as SSHHostTrust from .ssh_session_list import SSHSessionList as SSHSessionList @@ -17,6 +18,4 @@ from .execution_list_params import ExecutionListParams as ExecutionListParams from .execution_create_params import ExecutionCreateParams as ExecutionCreateParams from .execution_events_params import ExecutionEventsParams as ExecutionEventsParams -from .connect_client_event import ConnectClientEvent as ConnectClientEvent -from .connect_client_event_param import ConnectClientEventParam as ConnectClientEventParam -from .connect_server_event import ConnectServerEvent as ConnectServerEvent +from .autoresizing_update_params import AutoresizingUpdateParams as AutoresizingUpdateParams diff --git a/src/dedalus_sdk/types/machines/autoresizing_update_params.py b/src/dedalus_sdk/types/machines/autoresizing_update_params.py new file mode 100644 index 0000000..a70e87b --- /dev/null +++ b/src/dedalus_sdk/types/machines/autoresizing_update_params.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["AutoresizingUpdateParams"] + + +class AutoresizingUpdateParams(TypedDict, total=False): + machine_id: Required[str] + """Bare, lowercase, hyphenated Machine UUID. Pass the returned machine_id unchanged.""" + + enabled: Required[bool] diff --git a/src/dedalus_sdk/types/machines/connect_client_event.py b/src/dedalus_sdk/types/machines/connect_client_event.py deleted file mode 100644 index 7470d04..0000000 --- a/src/dedalus_sdk/types/machines/connect_client_event.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing import Union -from typing_extensions import TypeAlias - -from ..._models import BaseModel - -__all__ = ["ConnectClientEvent", "WebSocketEvent"] - - -class WebSocketEvent(BaseModel): - pass - - -ConnectClientEvent: TypeAlias = WebSocketEvent diff --git a/src/dedalus_sdk/types/machines/connect_client_event_param.py b/src/dedalus_sdk/types/machines/connect_client_event_param.py deleted file mode 100644 index 1e5f97c..0000000 --- a/src/dedalus_sdk/types/machines/connect_client_event_param.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing import Union -from typing_extensions import TypeAlias, TypedDict - -__all__ = ["ConnectClientEventParam", "WebSocketEvent"] - - -class WebSocketEvent(TypedDict, total=False): - pass - - -ConnectClientEventParam: TypeAlias = Union[WebSocketEvent] diff --git a/src/dedalus_sdk/types/machines/connect_server_event.py b/src/dedalus_sdk/types/machines/connect_server_event.py deleted file mode 100644 index 7934662..0000000 --- a/src/dedalus_sdk/types/machines/connect_server_event.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing import Union -from typing_extensions import TypeAlias - -from ..._models import BaseModel - -__all__ = ["ConnectServerEvent", "WebSocketEvent"] - - -class WebSocketEvent(BaseModel): - pass - - -ConnectServerEvent: TypeAlias = WebSocketEvent diff --git a/src/dedalus_sdk/types/machines/executions/__init__.py b/src/dedalus_sdk/types/machines/executions/__init__.py new file mode 100644 index 0000000..9ad3d43 --- /dev/null +++ b/src/dedalus_sdk/types/machines/executions/__init__.py @@ -0,0 +1,6 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from .status import Status as Status +from .read_token import ReadToken as ReadToken diff --git a/src/dedalus_sdk/types/machines/executions/read_token.py b/src/dedalus_sdk/types/machines/executions/read_token.py new file mode 100644 index 0000000..60358be --- /dev/null +++ b/src/dedalus_sdk/types/machines/executions/read_token.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from datetime import datetime + +from ...._models import BaseModel + +__all__ = ["ReadToken"] + + +class ReadToken(BaseModel): + access_token: str + + base_url: str + + execution_id: str + + expires_at: datetime + + stream_id: str + + token_type: str diff --git a/src/dedalus_sdk/types/machines/executions/status.py b/src/dedalus_sdk/types/machines/executions/status.py new file mode 100644 index 0000000..36c3dfb --- /dev/null +++ b/src/dedalus_sdk/types/machines/executions/status.py @@ -0,0 +1,40 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ...._models import BaseModel + +__all__ = ["Status", "Capture", "Publication"] + + +class Publication(BaseModel): + code: Optional[str] = None + + complete: bool + + queued_messages: int + + state: Literal["active", "finishing", "failed", "closed"] + + +class Capture(BaseModel): + code: Optional[str] = None + + lost_bytes: Optional[str] = None + + state: Optional[Literal["pending", "incomplete", "unavailable"]] = None + + unconfirmed_bytes: Optional[str] = None + + +class Status(BaseModel): + capture: Capture + + code: Optional[str] = None + + execution_id: str + + publication: Optional[Publication] = None + + stream_id: Optional[str] = None diff --git a/src/dedalus_sdk/types/machines/settings.py b/src/dedalus_sdk/types/machines/settings.py new file mode 100644 index 0000000..ced1e34 --- /dev/null +++ b/src/dedalus_sdk/types/machines/settings.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from ..._models import BaseModel + +__all__ = ["Settings"] + + +class Settings(BaseModel): + enabled: bool diff --git a/src/dedalus_sdk/types/organization/__init__.py b/src/dedalus_sdk/types/organization/__init__.py new file mode 100644 index 0000000..843c352 --- /dev/null +++ b/src/dedalus_sdk/types/organization/__init__.py @@ -0,0 +1,6 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from .policy import Policy as Policy +from .autoresizing_update_params import AutoresizingUpdateParams as AutoresizingUpdateParams diff --git a/src/dedalus_sdk/types/organization/autoresizing_update_params.py b/src/dedalus_sdk/types/organization/autoresizing_update_params.py new file mode 100644 index 0000000..998d8cd --- /dev/null +++ b/src/dedalus_sdk/types/organization/autoresizing_update_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["AutoresizingUpdateParams"] + + +class AutoresizingUpdateParams(TypedDict, total=False): + enabled: Required[bool] + """Allow automatic RAM increases for all organization machines. Disabling preserves applied RAM and already admitted resizes.""" diff --git a/src/dedalus_sdk/types/organization/policy.py b/src/dedalus_sdk/types/organization/policy.py new file mode 100644 index 0000000..abd22ac --- /dev/null +++ b/src/dedalus_sdk/types/organization/policy.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Scalar. See README.md for details. + +from ..._models import BaseModel + +__all__ = ["Policy"] + + +class Policy(BaseModel): + enabled: bool + """Allow automatic RAM increases for all organization machines. Disabling preserves applied RAM and already admitted resizes.""" diff --git a/src/dedalus_sdk/types/websocket_connection_options.py b/src/dedalus_sdk/types/websocket_connection_options.py deleted file mode 100644 index a67161d..0000000 --- a/src/dedalus_sdk/types/websocket_connection_options.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -from typing import TYPE_CHECKING -from typing_extensions import Sequence, TypedDict - -if TYPE_CHECKING: - from websockets import Subprotocol - from websockets.extensions import ClientExtensionFactory - - -class WebSocketConnectionOptions(TypedDict, total=False): - """WebSocket connection options forwarded to `websockets.connect`.""" - - extensions: Sequence[ClientExtensionFactory] | None - subprotocols: Sequence[Subprotocol] | None - compression: str | None - max_size: int | None - max_queue: int | None | tuple[int | None, int | None] - write_limit: int | tuple[int, int | None] diff --git a/src/dedalus_sdk/types/websocket_reconnection.py b/src/dedalus_sdk/types/websocket_reconnection.py deleted file mode 100644 index e4a5ce2..0000000 --- a/src/dedalus_sdk/types/websocket_reconnection.py +++ /dev/null @@ -1,36 +0,0 @@ -# File generated from our OpenAPI spec by Scalar. See README.md for details. - -from __future__ import annotations - -import dataclasses -from typing_extensions import TypedDict - -from .._types import Query, Headers - - -@dataclasses.dataclass(frozen=True) -class ReconnectingEvent: - """Information about a reconnection attempt passed to `on_reconnecting`.""" - - attempt: int - max_attempts: int - delay: float - close_code: int - extra_query: Query - extra_headers: Headers - - -class ReconnectingOverrides(TypedDict, total=False): - """Optional overrides for the next WebSocket reconnection attempt.""" - - extra_query: Query - extra_headers: Headers - abort: bool - - -_RECOVERABLE_CLOSE_CODES: frozenset[int] = frozenset({1001, 1005, 1006, 1011, 1012, 1013, 1015}) - - -def is_recoverable_close(code: int) -> bool: - """Return `True` if the WebSocket close code is worth retrying.""" - return code in _RECOVERABLE_CLOSE_CODES diff --git a/tests/smoke-test.py b/tests/smoke-test.py index 92c5fa3..23daa51 100644 --- a/tests/smoke-test.py +++ b/tests/smoke-test.py @@ -105,12 +105,27 @@ def _smoke_case_7() -> None: def _smoke_case_8() -> None: - page = client.machines.ssh.list( + machine = client.machines.reboot( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + idempotency_key="", ) def _smoke_case_9() -> None: + machine = client.machines.reboot( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + force=True, + idempotency_key="", + ) + + +def _smoke_case_10() -> None: + page = client.machines.ssh.list( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + ) + + +def _smoke_case_11() -> None: ssh = client.machines.ssh.create( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", public_key="", @@ -118,14 +133,14 @@ def _smoke_case_9() -> None: ) -def _smoke_case_10() -> None: +def _smoke_case_12() -> None: ssh = client.machines.ssh.retrieve( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", ) -def _smoke_case_11() -> None: +def _smoke_case_13() -> None: ssh = client.machines.ssh.delete( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", session_id="sessionID", @@ -133,13 +148,13 @@ def _smoke_case_11() -> None: ) -def _smoke_case_12() -> None: +def _smoke_case_14() -> None: page = client.machines.executions.list( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", ) -def _smoke_case_13() -> None: +def _smoke_case_15() -> None: execution = client.machines.executions.create( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", command=[""], @@ -147,7 +162,7 @@ def _smoke_case_13() -> None: ) -def _smoke_case_14() -> None: +def _smoke_case_16() -> None: execution = client.machines.executions.create( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", command=[""], @@ -159,14 +174,14 @@ def _smoke_case_14() -> None: ) -def _smoke_case_15() -> None: +def _smoke_case_17() -> None: execution = client.machines.executions.retrieve( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) -def _smoke_case_16() -> None: +def _smoke_case_18() -> None: execution = client.machines.executions.delete( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", @@ -174,32 +189,66 @@ def _smoke_case_16() -> None: ) -def _smoke_case_17() -> None: +def _smoke_case_19() -> None: execution = client.machines.executions.output( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) -def _smoke_case_18() -> None: +def _smoke_case_20() -> None: page = client.machines.executions.events( machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", execution_id="executionID", ) -def _smoke_case_19() -> None: - def _probe() -> None: - with client.machines.terminals.connect( - machine_id="machineID", - terminal_id="terminalID", - ) as socket: - try: - socket.recv() - finally: - socket.close(code=1000, reason="smoke-test") +def _smoke_case_21() -> None: + log = client.machines.executions.logs.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + ) + + +def _smoke_case_22() -> None: + log = client.machines.executions.logs.reauthorize( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", + ) + + +def _smoke_case_23() -> None: + log = client.machines.executions.logs.create_token( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + execution_id="executionID", + idempotency_key="", + ) + + +def _smoke_case_24() -> None: + autoresizing = client.machines.autoresizing.retrieve( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + ) + + +def _smoke_case_25() -> None: + autoresizing = client.machines.autoresizing.update( + machine_id="017f22e2-79b0-7cc3-98c4-dc0c0c07398f", + enabled=False, + idempotency_key="", + ) + - _probe() +def _smoke_case_26() -> None: + autoresizing = client.organization.autoresizing.retrieve() + + +def _smoke_case_27() -> None: + autoresizing = client.organization.autoresizing.update( + enabled=False, + idempotency_key="", + ) cases: list[SmokeCase] = [ @@ -253,79 +302,129 @@ def _probe() -> None: "path": "/v1/machines/{machine_id}/wake", "run": _smoke_case_7, }, + { + "operation": "reboot", + "method": "POST", + "path": "/v1/machines/{machine_id}/reboot", + "label": "required params", + "run": _smoke_case_8, + }, + { + "operation": "reboot", + "method": "POST", + "path": "/v1/machines/{machine_id}/reboot", + "label": "all params", + "run": _smoke_case_9, + }, { "operation": "list", "method": "GET", "path": "/v1/machines/{machine_id}/ssh", - "run": _smoke_case_8, + "run": _smoke_case_10, }, { "operation": "create", "method": "POST", "path": "/v1/machines/{machine_id}/ssh", - "run": _smoke_case_9, + "run": _smoke_case_11, }, { "operation": "retrieve", "method": "GET", "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "run": _smoke_case_10, + "run": _smoke_case_12, }, { "operation": "delete", "method": "DELETE", "path": "/v1/machines/{machine_id}/ssh/{session_id}", - "run": _smoke_case_11, + "run": _smoke_case_13, }, { "operation": "list", "method": "GET", "path": "/v1/machines/{machine_id}/executions", - "run": _smoke_case_12, + "run": _smoke_case_14, }, { "operation": "create", "method": "POST", "path": "/v1/machines/{machine_id}/executions", "label": "required params", - "run": _smoke_case_13, + "run": _smoke_case_15, }, { "operation": "create", "method": "POST", "path": "/v1/machines/{machine_id}/executions", "label": "all params", - "run": _smoke_case_14, + "run": _smoke_case_16, }, { "operation": "retrieve", "method": "GET", "path": "/v1/machines/{machine_id}/executions/{execution_id}", - "run": _smoke_case_15, + "run": _smoke_case_17, }, { "operation": "delete", "method": "DELETE", "path": "/v1/machines/{machine_id}/executions/{execution_id}", - "run": _smoke_case_16, + "run": _smoke_case_18, }, { "operation": "output", "method": "GET", "path": "/v1/machines/{machine_id}/executions/{execution_id}/output", - "run": _smoke_case_17, + "run": _smoke_case_19, }, { "operation": "events", "method": "GET", "path": "/v1/machines/{machine_id}/executions/{execution_id}/events", - "run": _smoke_case_18, + "run": _smoke_case_20, }, { - "operation": "connect", + "operation": "retrieve", "method": "GET", - "path": "/v1/machines/{machine_id}/terminals/{terminal_id}/stream", - "run": _smoke_case_19, + "path": "/v1/machines/{machine_id}/executions/{execution_id}/logs", + "run": _smoke_case_21, + }, + { + "operation": "reauthorize", + "method": "POST", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/logs/reauthorize", + "run": _smoke_case_22, + }, + { + "operation": "createToken", + "method": "POST", + "path": "/v1/machines/{machine_id}/executions/{execution_id}/logs/token", + "run": _smoke_case_23, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/machines/{machine_id}/autoresizing", + "run": _smoke_case_24, + }, + { + "operation": "update", + "method": "PUT", + "path": "/v1/machines/{machine_id}/autoresizing", + "run": _smoke_case_25, + }, + { + "operation": "retrieve", + "method": "GET", + "path": "/v1/organization/autoresizing", + "run": _smoke_case_26, + }, + { + "operation": "update", + "method": "PUT", + "path": "/v1/organization/autoresizing", + "run": _smoke_case_27, }, ] From cee159b42bef9a8bd9485a2f1e18f24295ac8d0e Mon Sep 17 00:00:00 2001 From: scalarbot Date: Thu, 24 Sep 2026 19:40:21 +0000 Subject: [PATCH 4/6] chore(api): update generated SDK content 2 generated files changed with no detected API surface change (documentation, examples, or file content). Build: r2EG6dIaRKAVNT85HR2Jf --- src/dedalus_sdk/_client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dedalus_sdk/_client.py b/src/dedalus_sdk/_client.py index 2f55530..6117352 100644 --- a/src/dedalus_sdk/_client.py +++ b/src/dedalus_sdk/_client.py @@ -189,6 +189,7 @@ def default_headers(self) -> dict[str, str | Omit]: "X-Scalar-Async": "false", "User-Agent": "Dedalus-SDK", "X-SDK-Version": "1.0.0", + "X-Dedalus-Org-Id": self.dedalus_org_id if self.dedalus_org_id is not None else Omit(), **self._custom_headers, } @@ -428,6 +429,7 @@ def default_headers(self) -> dict[str, str | Omit]: "X-Scalar-Async": f"async:{get_async_library()}", "User-Agent": "Dedalus-SDK", "X-SDK-Version": "1.0.0", + "X-Dedalus-Org-Id": self.dedalus_org_id if self.dedalus_org_id is not None else Omit(), **self._custom_headers, } From c9d3d05f9e247e6f107a4aa4a49b3ad15f7b7ff6 Mon Sep 17 00:00:00 2001 From: "scalar-docs[bot]" <148485328+scalar-docs[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 19:40:39 +0000 Subject: [PATCH 5/6] release: 0.6.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 94 +++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/dedalus_sdk/_version.py | 2 +- 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2aca35a..4208b5c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.0" + ".": "0.6.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6df1404..83c73b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,99 @@ # Changelog +## [0.6.0](https://github.com/dedalus-labs/dedalus-python/compare/v0.5.0...v0.6.0) (2026-09-24) + + +### ⚠ BREAKING CHANGES + +* **api:** 3 breaking changes to the SDK surface. + - Removed `bearer` auth scheme `Bearer`. + - Removed operation `machines.terminals.connect` (`GET /v1/machines/{machine_id}/terminals/{terminal_id}/stream`). + - Removed optional property `RetrieveResponseHeaders.ETag`. +* **api:** 72 breaking changes to the SDK surface. + - Configuration of `bearer` auth scheme `BearerAuth` changed. + - Removed header param `X-Dedalus-Org-Id` from `machines.list`. + - Removed header param `X-Dedalus-Org-Id` from `machines.create`. + - Removed header param `X-Dedalus-Org-Id` from `machines.retrieve`. + - Removed header param `X-Dedalus-Org-Id` from `machines.update`. + - Removed header param `X-Dedalus-Org-Id` from `machines.delete`. + - Removed header param `X-Dedalus-Org-Id` from `machines.sleep`. + - Removed header param `X-Dedalus-Org-Id` from `machines.wake`. + - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.list`. + - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.create`. + - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.retrieve`. + - Removed header param `X-Dedalus-Org-Id` from `machines.ssh.delete`. + - Removed header param `X-Dedalus-Org-Id` from `machines.executions.list`. + - Removed header param `X-Dedalus-Org-Id` from `machines.executions.create`. + - Removed header param `X-Dedalus-Org-Id` from `machines.executions.retrieve`. + - Removed header param `X-Dedalus-Org-Id` from `machines.executions.delete`. + - Removed header param `X-Dedalus-Org-Id` from `machines.executions.output`. + - Removed header param `X-Dedalus-Org-Id` from `machines.executions.events`. + - Serialization or defaults of path param `machine_id` on `machines.terminals.connect` changed. + - Serialization or defaults of path param `terminal_id` on `machines.terminals.connect` changed. + - Removed header param `X-Dedalus-Org-Id` from `machines.terminals.connect`. + - Removed operation `machines.watch` (`GET /v1/machines/{machine_id}/status/stream`). + - Removed operation `machines.network.retrieve` (`GET /v1/machines/{machine_id}/network`). + - Removed operation `machines.artifacts.list` (`GET /v1/machines/{machine_id}/artifacts`). + - Removed operation `machines.artifacts.retrieve` (`GET /v1/machines/{machine_id}/artifacts/{artifact_id}`). + - Removed operation `machines.artifacts.delete` (`DELETE /v1/machines/{machine_id}/artifacts/{artifact_id}`). + - Removed operation `machines.ports.list` (`GET /v1/machines/{machine_id}/ports`). + - Removed operation `machines.ports.create` (`POST /v1/machines/{machine_id}/ports`). + - Removed operation `machines.ports.retrieve` (`GET /v1/machines/{machine_id}/ports/{port_id}`). + - Removed operation `machines.ports.delete` (`DELETE /v1/machines/{machine_id}/ports/{port_id}`). + - Removed operation `machines.terminals.list` (`GET /v1/machines/{machine_id}/terminals`). + - Removed operation `machines.terminals.create` (`POST /v1/machines/{machine_id}/terminals`). + - Removed operation `machines.terminals.retrieve` (`GET /v1/machines/{machine_id}/terminals/{terminal_id}`). + - Removed operation `machines.terminals.delete` (`DELETE /v1/machines/{machine_id}/terminals/{terminal_id}`). + - Removed operation `networks.retrieve` (`GET /v1/networks/{network_id}`). + - Removed operation `usage.retrieve` (`GET /v1/usage`). + - Removed operation `usage.machineCompute` (`GET /v1/usage/machines/compute`). + - Removed operation `usage.machineStorage` (`GET /v1/usage/machines/storage`). + - Added required property `execution.log_capture`. + - Property `execution.machine_id` type changed from `string` to `string`. + - Property `machine.machine_id` type changed from `string` to `string`. + - Added required property `lifecycle_status.memory_configured_mib`. + - Property `machine_detail_response.machine_id` type changed from `string` to `string`. + - Schema `machine_id_path_segment` shape changed. + - Property `machine_list_item.machine_id` type changed from `string` to `string`. + - Property `ssh_session.machine_id` type changed from `string` to `string`. + - Property `ssh_session.status` type changed from `enum(wake_in_progress | ready | closed | …)` to `enum(wake_in_progress | ssh_in_progress | ready | …)`. + - Removed optional property `CreateResponseHeaders.ETag`. + - Removed optional property `CreateResponseHeaders.X-Dedalus-Storage-Operation-Id`. + - Removed schema `artifact_list`. + - Removed schema `artifact`. + - Removed schema `port_create_params`. + - Removed schema `terminal_create_params`. + - Removed schema `machine_compute_usage`. + - Removed schema `machine_compute_usage_row`. + - Removed schema `machine_network`. + - Removed schema `machine_storage_usage`. + - Removed schema `machine_storage_usage_row`. + - Removed schema `network_gateway`. + - Removed schema `network`. + - Removed schema `port_list`. + - Removed schema `port`. + - Removed schema `terminal_client_event`. + - Removed schema `terminal_closed_event`. + - Removed schema `terminal_error_event`. + - Removed schema `terminal_input_event`. + - Removed schema `terminal_list`. + - Removed schema `terminal_output_event`. + - Removed schema `terminal_resize_event`. + - Removed schema `terminal`. + - Removed schema `terminal_server_event`. + - Removed schema `org_usage`. + +### Features + +* **api:** initial SDK generation ([e82ebbb](https://github.com/dedalus-labs/dedalus-python/commit/e82ebbb8e40f956ea1fe1b9205425b79d48123b1)) +* **api:** remove auth scheme Bearer (+25 more changes) ([5ad53fd](https://github.com/dedalus-labs/dedalus-python/commit/5ad53fdb1238c2bd715ff69459bf663deaa94a78)) +* **api:** update auth scheme BearerAuth (+122 more changes) ([b685f10](https://github.com/dedalus-labs/dedalus-python/commit/b685f1081dc426b11202d87a4b01ff56dcbe02c0)) + + +### Chores + +* **api:** update generated SDK content ([cee159b](https://github.com/dedalus-labs/dedalus-python/commit/cee159b42bef9a8bd9485a2f1e18f24295ac8d0e)) + ## 0.5.0 (2026-09-01) Full Changelog: [v0.4.0...v0.5.0](https://github.com/dedalus-labs/dedalus-python/compare/v0.4.0...v0.5.0) diff --git a/pyproject.toml b/pyproject.toml index e60f3a0..3ece763 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dedalus-sdk" -version = "0.1.0" # x-release-please-version +version = "0.6.0" # x-release-please-version description = "Controlplane API for Dedalus Cloud Services (DCS)." readme = "README.md" license = "Apache-2.0" diff --git a/src/dedalus_sdk/_version.py b/src/dedalus_sdk/_version.py index 6686d0b..d487cb2 100644 --- a/src/dedalus_sdk/_version.py +++ b/src/dedalus_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Scalar. See README.md for details. __title__ = "dedalus" -__version__ = "0.5.0" # x-release-please-version +__version__ = "0.6.0" # x-release-please-version From 7f640770aac7ec7d6df0e6e5bc2a1b35e7451b41 Mon Sep 17 00:00:00 2001 From: AgentWings <231182611+AgentWings@users.noreply.github.com> Date: Thu, 24 Sep 2026 14:56:57 -0700 Subject: [PATCH 6/6] fix(sdk): preserve API-compatible automatic retry identities --- src/dedalus_sdk/_base_client.py | 5 +++- tests/test_feedback_retry.py | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/test_feedback_retry.py diff --git a/src/dedalus_sdk/_base_client.py b/src/dedalus_sdk/_base_client.py index 68e2617..76c3b9d 100644 --- a/src/dedalus_sdk/_base_client.py +++ b/src/dedalus_sdk/_base_client.py @@ -890,7 +890,10 @@ def _should_retry(self, response: httpx.Response) -> bool: return False def _idempotency_key(self) -> str: - return f"scalar-python-retry-{uuid.uuid4()}" + # @custom start + # The API requires a compact UUIDv7; retries reuse this generated key. + return f"{time.time_ns() // 1_000_000:012x}7{uuid.uuid4().hex[13:]}" + # @custom end class _DefaultHttpxClient(httpx.Client): diff --git a/tests/test_feedback_retry.py b/tests/test_feedback_retry.py new file mode 100644 index 0000000..f51bfbe --- /dev/null +++ b/tests/test_feedback_retry.py @@ -0,0 +1,51 @@ +"""Verify automatic retry keys through the installed SDK's real request builder.""" + +from __future__ import annotations + +import re + +import httpx +import pytest + +from dedalus_sdk import Dedalus, AsyncDedalus + + +def transport(keys: list[str]) -> httpx.MockTransport: + def handle(request: httpx.Request) -> httpx.Response: + key = request.headers["Idempotency-Key"] + assert re.fullmatch(r"[0-9a-f]{12}7[0-9a-f]{3}[89ab][0-9a-f]{15}", key) + keys.append(key) + if len(keys) == 1: + return httpx.Response(503, json={}, headers={"retry-after-ms": "1"}) + return httpx.Response(201, json={"id": "fb_" + key}) + + return httpx.MockTransport(handle) + + +def verify(keys: list[str]) -> None: + assert len(keys) == 3 + assert keys[0] == keys[1] + assert keys[1] != keys[2] + + +@pytest.mark.asyncio +async def test_invariant_async_retry_preserves_valid_feedback_identity() -> None: + keys: list[str] = [] + http_client = httpx.AsyncClient(transport=transport(keys)) + async with AsyncDedalus( + base_url="https://feedback.invalid", api_key="fixture", max_retries=1, http_client=http_client + ) as client: + await client.post("/v1/feedback", cast_to=httpx.Response, body={"message": "fixture", "source": "cli"}) + await client.post("/v1/feedback", cast_to=httpx.Response, body={"message": "new submission", "source": "cli"}) + verify(keys) + + +def test_invariant_sync_retry_preserves_valid_feedback_identity() -> None: + keys: list[str] = [] + http_client = httpx.Client(transport=transport(keys)) + with Dedalus( + base_url="https://feedback.invalid", api_key="fixture", max_retries=1, http_client=http_client + ) as client: + client.post("/v1/feedback", cast_to=httpx.Response, body={"message": "fixture", "source": "cli"}) + client.post("/v1/feedback", cast_to=httpx.Response, body={"message": "new submission", "source": "cli"}) + verify(keys)