cai/tests/continuous_ops/test_wizard_worker_python_b...

124 lines
4.2 KiB
Python

"""Wizard picks venv interpreter for worker when VIRTUAL_ENV is set."""
from __future__ import annotations
import sys
from pathlib import Path
from cai.continuous_ops import wizard
def test_probe_cai_import_succeeds_on_current_interpreter() -> None:
import sys
ok, err = wizard._probe_cai_import_on_python(sys.executable)
assert ok is True
assert err == ""
def test_worker_python_bin_prefers_venv(monkeypatch, tmp_path: Path) -> None:
venv = tmp_path / "venv"
(venv / "bin").mkdir(parents=True)
py = venv / "bin" / "python3"
py.write_text("#!/bin/sh\necho\n", encoding="utf-8")
py.chmod(0o755)
monkeypatch.setenv("VIRTUAL_ENV", str(venv))
out = wizard._worker_python_bin()
assert out == str(py.resolve())
def test_worker_python_bin_fallback(monkeypatch) -> None:
monkeypatch.delenv("VIRTUAL_ENV", raising=False)
out = wizard._worker_python_bin()
assert Path(out).name.startswith("python") or "python" in out.lower()
def test_loop_python_for_run_script_follows_cai_launcher_venv(monkeypatch, tmp_path: Path) -> None:
"""When VIRTUAL_ENV is unset but ``cai`` is ``.../env/bin/cai``, use that env's python3."""
venv = tmp_path / "myenv"
bin_dir = venv / "bin"
bin_dir.mkdir(parents=True)
cai_sh = bin_dir / "cai"
cai_sh.write_text("#!/bin/sh\necho\n", encoding="utf-8")
cai_sh.chmod(0o755)
py3 = bin_dir / "python3"
py3.write_text("#!/bin/sh\necho\n", encoding="utf-8")
py3.chmod(0o755)
monkeypatch.delenv("VIRTUAL_ENV", raising=False)
py3_res = str(py3.resolve())
def _probe(py: str) -> tuple[bool, str]:
if py == py3_res:
return True, ""
return wizard._probe_cai_import_on_python(py)
monkeypatch.setattr(wizard, "_probe_cai_import_on_python", _probe)
out = wizard._loop_python_for_run_script([str(cai_sh.resolve())])
assert out == py3_res
def test_loop_python_falls_back_to_checkout_cai_env_when_shim_python_lacks_cai(
monkeypatch, tmp_path: Path
) -> None:
"""``*/bin/cai`` with a sibling ``python3`` that cannot import ``cai`` must not win over ``cai_env``."""
usr_bin = tmp_path / "fake_usr" / "bin"
usr_bin.mkdir(parents=True)
cai_sh = usr_bin / "cai"
cai_sh.write_text("#!/bin/sh\necho shim\n", encoding="utf-8")
cai_sh.chmod(0o755)
bad_py = usr_bin / "python3"
bad_py.write_text("#!/bin/sh\necho bad\n", encoding="utf-8")
bad_py.chmod(0o755)
venv = tmp_path / "cai_env"
(venv / "bin").mkdir(parents=True)
good_py = venv / "bin" / "python3"
good_py.write_text("#!/bin/sh\necho good\n", encoding="utf-8")
good_py.chmod(0o755)
good_res = str(good_py.resolve())
def _probe(py: str) -> tuple[bool, str]:
if py == good_res:
return True, ""
return False, "no module named cai"
monkeypatch.setattr(wizard, "_probe_cai_import_on_python", _probe)
monkeypatch.setattr(wizard, "_wizard_checkout_root_for_loop_python", lambda: tmp_path)
monkeypatch.setattr(wizard, "_worker_python_bin", lambda: str(bad_py.resolve()))
monkeypatch.delenv("VIRTUAL_ENV", raising=False)
out = wizard._loop_python_for_run_script([str(cai_sh.resolve())])
assert out == good_res
def test_loop_python_returns_venv_bin_path_when_python3_symlinks_to_system(
monkeypatch, tmp_path: Path
) -> None:
"""``venv/bin/python3`` → ``/usr/bin/python3*``: must not collapse shebang to the system path."""
bin_dir = tmp_path / "myvenv" / "bin"
bin_dir.mkdir(parents=True)
py = bin_dir / "python3"
try:
py.symlink_to(Path(sys.executable).resolve())
except OSError:
import pytest
pytest.skip("cannot create symlink for test")
cai_sh = bin_dir / "cai"
cai_sh.write_text("#!/bin/sh\necho\n", encoding="utf-8")
cai_sh.chmod(0o755)
want = str(py.absolute())
assert Path(want).resolve() == Path(sys.executable).resolve()
def _probe(py: str) -> tuple[bool, str]:
if py == want:
return True, ""
return False, "no cai"
monkeypatch.setattr(wizard, "_probe_cai_import_on_python", _probe)
monkeypatch.delenv("VIRTUAL_ENV", raising=False)
out = wizard._loop_python_for_run_script([str(cai_sh.resolve())])
assert out == want