Download tests/test_hosting.py from Farshadm/beampilot: direct link, hf CLI and curl.
- Browser
- Download file 14 kB
-
https://huggingface.co/spaces/Farshadm/beampilot/resolve/main/tests/test_hosting.py
- Command line
-
hf download hf://spaces/Farshadm/beampilot/tests/test_hosting.py
-
curl -L -o test_hosting.py https://huggingface.co/spaces/Farshadm/beampilot/resolve/main/tests/test_hosting.py
14 kB
| """Hosted demo (Hugging Face Space): live-run guards, key safety, shipped files. | |
| See docs/hosting-plan.md, sections 2-5. | |
| """ | |
| import csv | |
| import getpass | |
| import json | |
| import re | |
| import runpy | |
| import subprocess | |
| import sys | |
| from datetime import date | |
| from pathlib import Path | |
| from types import SimpleNamespace | |
| import httpx2 # the HTTP library of the openai SDK (not httpx) | |
| import pytest | |
| from test_demo import _lens_script_client, _scripted_client | |
| from beampilot import app as demo_app | |
| from beampilot.agent import AgentConfig | |
| REPO = Path(__file__).resolve().parents[1] | |
| SENTINEL = "dummy-key-SENTINEL-7f3a9c" | |
| def clean_env(monkeypatch): | |
| for name in ("BEAMPILOT_LIVE_RUNS", "BEAMPILOT_SPEND_CAP_USD"): | |
| monkeypatch.delenv(name, raising=False) | |
| monkeypatch.setattr(demo_app, "_GLOBAL", demo_app.GlobalBudget()) | |
| def _request(name: str) -> SimpleNamespace: | |
| demo_app._BROWSERS.pop(name, None) | |
| return SimpleNamespace(session_hash=name) | |
| # Spend cap (BEAMPILOT_SPEND_CAP_USD) | |
| def test_spend_cap_is_read_from_the_environment(monkeypatch) -> None: | |
| monkeypatch.setenv("BEAMPILOT_SPEND_CAP_USD", "0.3") | |
| assert demo_app.spend_cap_from_env() == 0.3 | |
| assert demo_app.GlobalBudget().spend_cap_usd == 0.3 | |
| for bad in ("", "lots", "-1", "0", "inf", "nan"): | |
| monkeypatch.setenv("BEAMPILOT_SPEND_CAP_USD", bad) | |
| assert demo_app.spend_cap_from_env() == demo_app.DEFAULT_SPEND_CAP_USD == 5.0 | |
| def test_spend_cap_admits_a_run_only_if_a_worst_case_run_still_fits() -> None: | |
| budget = demo_app.GlobalBudget(spend_cap_usd=1.0) | |
| assert budget.reserve() is None # 0 + 0.55 <= 1 | |
| assert budget.reserved_usd == pytest.approx(0.55) | |
| budget.add_cost(0.40) | |
| budget.release() | |
| assert budget.reserved_usd == 0.0 | |
| assert budget.reserve() is None # 0.40 + 0.55 = 0.95 <= 1 | |
| budget.add_cost(0.10) | |
| budget.release() | |
| # 0.50 + 0.55 = 1.05 > 1: the next run could overshoot the cap. | |
| assert budget.out_of_budget() == demo_app.BUDGET_TEXT | |
| assert budget.reserve() == demo_app.BUDGET_TEXT | |
| assert budget.runs == 2 and budget.active == 0 | |
| def test_a_run_that_never_started_frees_its_reserve() -> None: | |
| budget = demo_app.GlobalBudget(spend_cap_usd=0.6) | |
| assert budget.reserve() is None | |
| budget.release(started=False) | |
| assert budget.runs == 0 and budget.reserved_usd == 0.0 | |
| assert budget.out_of_budget() is None | |
| def test_live_runs_add_their_cost_and_stop_at_the_cap(monkeypatch, tmp_path) -> None: | |
| monkeypatch.setattr(demo_app, "_client", _scripted_client) | |
| monkeypatch.setattr(demo_app, "LIVE_RUNS_DIR", tmp_path) | |
| monkeypatch.setattr(demo_app, "_GLOBAL", demo_app.GlobalBudget(spend_cap_usd=0.6)) | |
| list(demo_app.live_run("clean", 0, "", _request("spend-1"))) | |
| (saved,) = tmp_path.glob("*.json") | |
| cost = json.loads(saved.read_text(encoding="utf-8"))["cost_usd"] | |
| assert cost > 0 | |
| assert demo_app._GLOBAL.spent_usd == pytest.approx(cost, abs=1e-5) | |
| assert demo_app._GLOBAL.reserved_usd == 0.0 | |
| demo_app._GLOBAL.add_cost(0.6 - 0.55 - demo_app._GLOBAL.spent_usd + 0.01) | |
| update = next(demo_app.live_run("clean", 0, "", _request("spend-2"))) | |
| assert update[2] == demo_app.BUDGET_TEXT | |
| # Live switch (BEAMPILOT_LIVE_RUNS) and the page banner | |
| def test_live_switch_values(monkeypatch) -> None: | |
| for off in ("off", "OFF", " false ", "0", "no"): | |
| monkeypatch.setenv("BEAMPILOT_LIVE_RUNS", off) | |
| assert not demo_app.live_switch_on() | |
| for on in ("on", "", "yes", "1"): | |
| monkeypatch.setenv("BEAMPILOT_LIVE_RUNS", on) | |
| assert demo_app.live_switch_on() | |
| def test_switched_off_live_runs_never_start(monkeypatch) -> None: | |
| def no_client(): | |
| raise AssertionError("no client may be made when live runs are off") | |
| monkeypatch.setattr(demo_app, "_client", no_client) | |
| monkeypatch.setenv("BEAMPILOT_LIVE_RUNS", "off") | |
| request = _request("switch-off") | |
| update = next(demo_app.live_run("clean", 0, "", request)) | |
| assert update[2] == demo_app.LIVE_OFF_TEXT | |
| assert demo_app._GLOBAL.runs == 0 and demo_app._browser(request).runs == 0 | |
| def test_banner_and_start_button_at_page_load(monkeypatch, tmp_path) -> None: | |
| monkeypatch.chdir(tmp_path) # no .env here | |
| monkeypatch.delenv("MODEL_API_KEY", raising=False) | |
| banner, enabled = demo_app.live_banner() | |
| assert demo_app.NO_KEY_TEXT in banner and not enabled | |
| assert "MODEL_API_KEY" in banner # the variable's name, never a value | |
| monkeypatch.setenv("BEAMPILOT_LIVE_RUNS", "off") # checked first | |
| banner, enabled = demo_app.live_banner() | |
| assert demo_app.LIVE_OFF_TEXT in banner and not enabled | |
| monkeypatch.delenv("BEAMPILOT_LIVE_RUNS") | |
| monkeypatch.setenv("MODEL_API_KEY", SENTINEL) | |
| assert demo_app.live_banner() == ("", True) | |
| assert SENTINEL not in json.dumps(demo_app.live_banner()) | |
| monkeypatch.setenv("BEAMPILOT_SPEND_CAP_USD", "0.3") # below one worst-case run | |
| monkeypatch.setattr(demo_app, "_GLOBAL", demo_app.GlobalBudget()) | |
| banner, enabled = demo_app.live_banner() | |
| assert demo_app.BUDGET_TEXT in banner and not enabled | |
| def test_live_runs_have_a_queue_of_one_and_replays_do_not_wait() -> None: | |
| pytest.importorskip("gradio") | |
| app = demo_app.build_app() | |
| fns = {getattr(f.fn, "__name__", ""): f for f in app.fns.values()} | |
| assert demo_app.MAX_CONCURRENT_RUNS == 1 | |
| assert fns["start_run"].concurrency_limit == 1 | |
| assert fns["start_run"].concurrency_id == "live" | |
| assert fns["replay"].concurrency_id != "live" | |
| assert fns["replay"].concurrency_limit == "default" # REPLAY_CONCURRENCY | |
| # Live lens runs use the v3 limits; normal runs keep theirs. | |
| def _saved_config(tmp_path: Path) -> dict: | |
| (saved,) = tmp_path.glob("*.json") | |
| return json.loads(saved.read_text(encoding="utf-8"))["config"] | |
| def test_live_lens_runs_use_the_v3_limits(monkeypatch, tmp_path) -> None: | |
| monkeypatch.setattr(demo_app, "_client", _lens_script_client) | |
| monkeypatch.setattr(demo_app, "LIVE_RUNS_DIR", tmp_path) | |
| request = _request("lens-limits") | |
| list(demo_app.live_run("waist_outside_range", 0, "", request, lens_kit=True)) | |
| config = _saved_config(tmp_path) | |
| assert config["max_model_calls"] == 80 | |
| assert config["max_total_tokens"] == 3_000_000 | |
| assert config["max_cost_usd"] == 0.50 | |
| assert config["change_lens"] is True | |
| assert demo_app._browser(request).session.scenario.max_positions == 28 | |
| def test_normal_live_runs_keep_their_limits(monkeypatch, tmp_path) -> None: | |
| monkeypatch.setattr(demo_app, "_client", _scripted_client) | |
| monkeypatch.setattr(demo_app, "LIVE_RUNS_DIR", tmp_path) | |
| list(demo_app.live_run("clean", 0, "", _request("normal-limits"))) | |
| config, default = _saved_config(tmp_path), AgentConfig() | |
| assert config["max_model_calls"] == default.max_model_calls | |
| assert config["max_total_tokens"] == default.max_total_tokens | |
| assert config["max_cost_usd"] == default.max_cost_usd | |
| assert not config.get("change_lens") | |
| # The key never reaches the UI, a run file or the console. | |
| def test_dummy_key_never_reaches_ui_run_file_or_console( | |
| monkeypatch, tmp_path, capfd | |
| ) -> None: | |
| """The real client with a fake server that echoes the key in its error.""" | |
| import openai | |
| seen = [] | |
| def server(request: httpx2.Request) -> httpx2.Response: | |
| auth = request.headers.get("authorization", "") | |
| seen.append(auth) | |
| message = f"Incorrect API key provided: {auth}" | |
| return httpx2.Response(401, json={"error": {"message": message}}) | |
| real = openai.OpenAI | |
| def offline_openai(*args, **kwargs): | |
| transport = httpx2.MockTransport(server) | |
| return real(*args, http_client=httpx2.Client(transport=transport), **kwargs) | |
| monkeypatch.setattr(openai, "OpenAI", offline_openai) | |
| monkeypatch.setattr(demo_app, "_CLIENT", None) # build a fresh client | |
| monkeypatch.setattr(demo_app, "LIVE_RUNS_DIR", tmp_path) | |
| monkeypatch.setenv("MODEL_API_KEY", SENTINEL) | |
| updates = list(demo_app.live_run("clean", 0, "", _request("sentinel"))) | |
| assert seen and SENTINEL in seen[0] # the key really went to the server | |
| shown = json.dumps(updates, default=str) | |
| assert SENTINEL not in shown | |
| assert "AuthenticationError (HTTP 401)" in shown | |
| files = list(tmp_path.glob("*.json")) | |
| assert files | |
| for path in files: | |
| assert SENTINEL not in path.read_text(encoding="utf-8") | |
| out, err = capfd.readouterr() | |
| assert SENTINEL not in out and SENTINEL not in err | |
| # Shipped replay files | |
| def _personal_strings() -> set[str]: | |
| """Local user name, home folder and git e-mail of whoever runs the tests.""" | |
| values = {getpass.getuser(), Path.home().name} | |
| try: | |
| email = subprocess.run( | |
| ["git", "config", "user.email"], | |
| capture_output=True, | |
| text=True, | |
| cwd=REPO, | |
| timeout=10, | |
| ).stdout.strip() | |
| except (OSError, subprocess.SubprocessError): | |
| email = "" | |
| if "@" in email: | |
| values |= {email, email.split("@", 1)[1]} | |
| generic = {"runner", "root", "user", "admin", "home"} | |
| return {v.lower() for v in values if len(v) >= 4 and v.lower() not in generic} | |
| FORBIDDEN = { | |
| "Windows path": re.compile(r"[A-Za-z]:(\\\\|/)"), | |
| "home path": re.compile(r"/(home|Users)/\w"), | |
| "e-mail address": re.compile(r"[\w.+-]+@[\w-]+\.[A-Za-z]{2,}"), | |
| "key-like string": re.compile(r"\bsk-[A-Za-z0-9_-]{8,}|Bearer\s", re.IGNORECASE), | |
| "key name": re.compile(r"api[_-]?key|MODEL_API_KEY|BASETEN", re.IGNORECASE), | |
| } | |
| def test_shipped_run_files_hold_no_paths_names_or_keys() -> None: | |
| personal = _personal_strings() | |
| runs = demo_app.demo_runs() | |
| assert len(runs) == 5 | |
| for path in runs: | |
| text = path.read_text(encoding="utf-8") | |
| for kind, pattern in FORBIDDEN.items(): | |
| match = pattern.search(text) | |
| assert match is None, f"{path.name}: {kind} {match.group(0)!r}" | |
| lowered = text.lower() | |
| assert not [v for v in personal if v in lowered], path.name | |
| def test_every_replay_has_a_recording_date() -> None: | |
| with demo_app.RECORDED_MANIFEST.open(encoding="utf-8", newline="") as handle: | |
| rows = list(csv.DictReader(handle)) | |
| assert {row["file"] for row in rows} == {p.name for p in demo_app.demo_runs()} | |
| for row in rows: | |
| assert date.fromisoformat(row["recorded"]) >= date(2026, 10, 26) | |
| assert row["source"] | |
| def test_replays_are_labelled_as_recorded(tmp_path) -> None: | |
| for label, value in demo_app.replay_choices(): | |
| assert re.match(r"Recorded run, 2026-\d\d-\d\d, muse-spark-1\.2: ", label) | |
| assert (REPO / value).exists() | |
| shipped = (demo_app.DEMO_RUNS_DIR / "lens_v3_L5.json").relative_to(REPO) | |
| title = list(demo_app.replay(shipped.as_posix(), None, 0.0))[-1][0] | |
| assert "Recorded run, 2026-10-31, muse-spark-1.2" in title | |
| assert "a replay, not a live run" in title and "L5 (seed 904)" in title | |
| upload = tmp_path / "lens_v3_L5.json" # same name, but uploaded | |
| upload.write_bytes((REPO / shipped).read_bytes()) | |
| title = list(demo_app.replay(None, str(upload), 0.0))[-1][0] | |
| assert "Recorded run, date unknown, muse-spark-1.2" in title | |
| # Space files: requirements, front matter, entry point | |
| def _requirement_name(spec: str) -> str: | |
| name = re.split(r"[<>=!~;\[ ]", spec.strip(), maxsplit=1)[0] | |
| return name.lower().replace("_", "-") | |
| def test_requirements_pin_exactly_the_project_dependencies() -> None: | |
| tomllib = pytest.importorskip("tomllib") | |
| project = tomllib.loads((REPO / "pyproject.toml").read_text(encoding="utf-8")) | |
| wanted = {_requirement_name(d) for d in project["project"]["dependencies"]} | |
| lines = (REPO / "requirements.txt").read_text(encoding="utf-8").splitlines() | |
| specs = [line.strip() for line in lines if line.strip() and line[0] != "#"] | |
| assert all(re.fullmatch(r"[A-Za-z0-9_.-]+==[0-9][\w.]*", s) for s in specs) | |
| assert {_requirement_name(s) for s in specs} == wanted | |
| assert "gradio" not in wanted # pinned by sdk_version instead | |
| def _front_matter(path: Path) -> dict[str, str]: | |
| text = path.read_text(encoding="utf-8") | |
| assert text.startswith("---\n") | |
| block = text[4 : text.index("\n---\n", 4)] | |
| pairs = (line.split(":", 1) for line in block.splitlines() if line.strip()) | |
| return {key.strip(): value.strip().strip('"') for key, value in pairs} | |
| def test_space_readme_front_matter_matches_the_project() -> None: | |
| meta = _front_matter(REPO / "space" / "README.md") | |
| pyproject = (REPO / "pyproject.toml").read_text(encoding="utf-8") | |
| gradio_pin = re.search(r'"gradio==([\d.]+)"', pyproject).group(1) | |
| assert meta["sdk"] == "gradio" | |
| assert meta["sdk_version"] == gradio_pin | |
| assert meta["python_version"] == "3.12" | |
| assert (REPO / meta["app_file"]).is_file() | |
| assert meta["license"] == "mit" | |
| assert meta["suggested_hardware"] == "cpu-basic" | |
| assert 0 < len(meta["short_description"]) <= 60 | |
| text = (REPO / "space" / "README.md").read_text(encoding="utf-8") | |
| assert "simulated" in text and "https://github.com/Farshadmhd/beampilot" in text | |
| # The GitHub README carries no front matter. | |
| assert not (REPO / "README.md").read_text(encoding="utf-8").startswith("---") | |
| def test_space_entry_point_runs_the_app_from_the_src_layout(monkeypatch) -> None: | |
| monkeypatch.setattr(sys, "path", list(sys.path)) | |
| namespace = runpy.run_path(str(REPO / "scripts" / "space_app.py"), run_name="x") | |
| assert namespace["main"] is demo_app.main | |
| assert str(REPO / "src") == sys.path[0] | |
| assert demo_app.DEMO_RUNS_DIR == REPO / "docs" / "runs" | |