25576b0be6
Checks (magui2.0) / python-lint (push) Failing after 1s
Checks (magui2.0) / python-test (push) Failing after 0s
Checks (magui2.0) / frontend-lint (push) Failing after 0s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
Checks (magui2.0) / python-format (push) Failing after 1s
CodeQL Advanced / Analyze (python) (push) Failing after 0s
Checks (magui2.0) / python-pyright (push) Failing after 1s
Checks (magui2.0) / frontend-format (push) Failing after 1s
Checks (magui2.0) / frontend-typecheck (push) Failing after 0s
Checks (magui2.0) / frontend-test (push) Failing after 2s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
"""Share one sandbox venv across the OmniAgent test suite.
|
|
|
|
Every ``NullSandbox`` builds a Python venv under its ``agent_home`` and installs
|
|
``markitdown[all]`` (``src/magentic_ui/sandbox/requirements.txt``). These tests
|
|
use a per-test ``tmp_path`` as both workspace and (by default) ``agent_home``,
|
|
so each test rebuilt that heavy venv from scratch. With enough tests, the
|
|
per-test venvs piled up in pytest's session temp tree and exhausted the CI
|
|
runner disk (``[Errno 28] No space left on device``).
|
|
|
|
This builds the venv once per session at a shared ``agent_home`` and points
|
|
every ``NullSandbox`` at it (unless a test passes its own ``agent_home``). Each
|
|
test keeps its own ``tmp_path`` workspace, so file isolation is unchanged — only
|
|
the venv is shared.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from magentic_ui.sandbox._local import _SANDBOX_REQUIREMENTS
|
|
from magentic_ui.sandbox._null import NullSandbox
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def shared_sandbox_agent_home(
|
|
tmp_path_factory: pytest.TempPathFactory,
|
|
) -> Path:
|
|
# Anchored under this run's pytest-<N> base dir so pytest's normal
|
|
# "keep last 3 runs" cleanup removes it — no manual teardown.
|
|
shared_home = tmp_path_factory.getbasetemp() / "sandbox_agent_home"
|
|
venv = shared_home / "sandbox" / "venv"
|
|
|
|
# Build the full venv once. Use uv (the project's package manager) so we
|
|
# don't depend on the system python3 shipping ensurepip. Tests run serially
|
|
# today; if pytest-xdist is added, guard this build with a cross-process
|
|
# lock and anchor ``shared_home`` at ``getbasetemp().parent`` so workers
|
|
# share it.
|
|
if not venv.exists():
|
|
venv.parent.mkdir(parents=True, exist_ok=True)
|
|
subprocess.run(["uv", "venv", str(venv)], check=True, capture_output=True)
|
|
subprocess.run(
|
|
[
|
|
"uv",
|
|
"pip",
|
|
"install",
|
|
"-q",
|
|
"--python",
|
|
str(venv / "bin" / "python"),
|
|
"-r",
|
|
str(_SANDBOX_REQUIREMENTS),
|
|
],
|
|
check=True,
|
|
)
|
|
return shared_home
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _redirect_null_sandbox_to_shared_venv(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
shared_sandbox_agent_home: Path,
|
|
) -> None:
|
|
# Function-scoped (and confined to this package's conftest) so the redirect
|
|
# is torn down after each test and never leaks onto NullSandbox usage in
|
|
# other test directories. Tests that pass an explicit ``agent_home`` keep
|
|
# it; everything else lands on the shared venv.
|
|
original_init = NullSandbox.__init__
|
|
|
|
def patched_init(
|
|
self: NullSandbox,
|
|
workspace: Path,
|
|
agent_home: Path | None = None,
|
|
reset: bool = False,
|
|
bash_only: bool = False,
|
|
) -> None:
|
|
original_init(
|
|
self,
|
|
workspace,
|
|
agent_home=agent_home
|
|
if agent_home is not None
|
|
else shared_sandbox_agent_home,
|
|
reset=reset,
|
|
bash_only=bash_only,
|
|
)
|
|
|
|
monkeypatch.setattr(NullSandbox, "__init__", patched_init)
|