Files
opensquilla--opensquilla/tests/test_tools/test_code_exec_python_resolution.py
2026-07-13 13:12:33 +08:00

111 lines
3.9 KiB
Python

from __future__ import annotations
import os
import stat
import sys
from pathlib import Path
from types import SimpleNamespace
import pytest
from opensquilla.sandbox import sensitive_paths
from opensquilla.tools.builtin import code_exec
from opensquilla.tools.types import ToolContext, current_tool_context
def test_code_exec_prefers_current_interpreter_when_path_has_no_python(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
python_bin = tmp_path / ("python.exe" if os.name == "nt" else "python")
python_bin.write_text("", encoding="utf-8")
python_bin.chmod(python_bin.stat().st_mode | stat.S_IXUSR)
monkeypatch.setattr(sys, "executable", str(python_bin))
monkeypatch.setattr(code_exec.shutil, "which", lambda _name: None)
assert code_exec._resolve_python_bin(sandbox_enabled=False) == str(python_bin)
def test_code_exec_prefers_current_interpreter_for_non_bubblewrap_sandbox(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
python_bin = tmp_path / ("python.exe" if os.name == "nt" else "python")
python_bin.write_text("", encoding="utf-8")
python_bin.chmod(python_bin.stat().st_mode | stat.S_IXUSR)
monkeypatch.setattr(sys, "executable", str(python_bin))
monkeypatch.setattr(code_exec.shutil, "which", lambda _name: None)
monkeypatch.setattr(
code_exec,
"get_runtime",
lambda: SimpleNamespace(backend=SimpleNamespace(name="noop")),
)
assert code_exec._resolve_python_bin(sandbox_enabled=True) == str(python_bin)
def test_code_exec_bubblewrap_sandbox_prefers_visible_system_python(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
host_python = tmp_path / ("venv-python.exe" if os.name == "nt" else "venv-python")
sandbox_python = tmp_path / ("python3.exe" if os.name == "nt" else "python3")
host_python.write_text("", encoding="utf-8")
sandbox_python.write_text("", encoding="utf-8")
host_python.chmod(host_python.stat().st_mode | stat.S_IXUSR)
sandbox_python.chmod(sandbox_python.stat().st_mode | stat.S_IXUSR)
monkeypatch.setattr(sys, "executable", str(host_python))
monkeypatch.setattr(code_exec.shutil, "which", lambda _name: None)
monkeypatch.setattr(code_exec, "_SANDBOX_PYTHON_CANDIDATES", (sandbox_python,))
monkeypatch.setattr(
code_exec,
"get_runtime",
lambda: SimpleNamespace(backend=SimpleNamespace(name="bubblewrap")),
)
assert code_exec._resolve_python_bin(sandbox_enabled=True) == str(sandbox_python)
def test_code_exec_allows_active_workspace_under_sensitive_parent(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
workspace = tmp_path / "workspace"
workspace.mkdir()
monkeypatch.setattr(sensitive_paths, "_SENSITIVE_PREFIXES", (str(tmp_path),))
monkeypatch.setattr(
sensitive_paths,
"_WORKSPACE_PARENT_EXCEPTION_MARKERS",
(str(tmp_path),),
)
token = current_tool_context.set(ToolContext(workspace_dir=str(workspace)))
try:
result = code_exec._check_code_sensitive_access(
f"from pathlib import Path\nprint(Path({str(workspace / 'data.txt')!r}).read_text())"
)
finally:
current_tool_context.reset(token)
assert result is None
def test_code_exec_workspace_exception_keeps_leaf_secret_blocks(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
workspace = tmp_path / "workspace"
workspace.mkdir()
monkeypatch.setattr(sensitive_paths, "_SENSITIVE_PREFIXES", (str(tmp_path),))
monkeypatch.setattr(
sensitive_paths,
"_WORKSPACE_PARENT_EXCEPTION_MARKERS",
(str(tmp_path),),
)
token = current_tool_context.set(ToolContext(workspace_dir=str(workspace)))
try:
result = code_exec._check_code_sensitive_access(
f"open({str(workspace / '.env')!r}).read()"
)
finally:
current_tool_context.reset(token)
assert result is not None
assert result[0] == "sensitive_path"