Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ dependencies = [
"loguru>=0.7.0",
"tomli-w>=1.0.0",
"renderers>=0.1.8.dev40",
"google-genai>=2.8.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update the lockfile for google-genai

Adding google-genai here makes the package depend on a module that is imported at client-config import time (verifiers/v1/clients/config.py imports from google import genai), but uv.lock was not updated — rg '^name = "google-genai"' uv.lock returns no entry. In any locked/reproducible install path such as CI or contributor uv sync --locked, this commit cannot install the new dependency and import verifiers.v1.clients will fail once the lockfile environment is used.

Useful? React with 👍 / 👎.

]

[dependency-groups]
Expand Down
67 changes: 67 additions & 0 deletions tests/test_threaded_sandbox_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from types import SimpleNamespace
from unittest.mock import AsyncMock

import pytest

from verifiers.utils import threaded_sandbox_client
from verifiers.utils.threaded_sandbox_client import ThreadedAsyncSandboxClient


@pytest.mark.asyncio
async def test_wait_for_creation_polls_with_short_worker_calls(
monkeypatch: pytest.MonkeyPatch,
) -> None:
sleeps: list[float] = []

async def sleep(seconds: float) -> None:
sleeps.append(seconds)

monkeypatch.setattr(threaded_sandbox_client.asyncio, "sleep", sleep)
monkeypatch.setattr(threaded_sandbox_client.random, "uniform", lambda *_: 1.2)
client = object.__new__(ThreadedAsyncSandboxClient)
client.metrics = {}
client.get = AsyncMock(
side_effect=[
SimpleNamespace(status="PENDING"),
SimpleNamespace(status="RUNNING"),
SimpleNamespace(status="RUNNING"),
]
)
client._is_sandbox_reachable = AsyncMock(return_value=True)

await client.wait_for_creation("sbx-1", stability_checks=2)

assert client.get.await_count == 3
assert client._is_sandbox_reachable.await_count == 2
assert sleeps == [1.2, 0.6]
assert client.metrics["readiness_polls"] == 3
assert client.metrics["readiness_seconds"] >= 0


@pytest.mark.asyncio
async def test_background_job_polling_adds_jitter_and_metrics(
monkeypatch: pytest.MonkeyPatch,
) -> None:
sleeps: list[float] = []

async def sleep(seconds: float) -> None:
sleeps.append(seconds)

monkeypatch.setattr(threaded_sandbox_client.asyncio, "sleep", sleep)
monkeypatch.setattr(threaded_sandbox_client.random, "uniform", lambda *_: 0.8)
client = object.__new__(ThreadedAsyncSandboxClient)
client.metrics = {}
client.start_background_job = AsyncMock(return_value="job-1")
client.get_background_job = AsyncMock(
side_effect=[
SimpleNamespace(completed=False),
SimpleNamespace(completed=True),
]
)

result = await client.run_background_job("sbx-1", "echo hi", poll_interval=2)

assert result.completed is True
assert sleeps == [1.6]
assert client.metrics["background_job_polls"] == 2
assert client.metrics["background_job_seconds"] >= 0
Comment thread
xeophon marked this conversation as resolved.
Outdated
Loading
Loading