Skip to content

Commit e59a2b1

Browse files
committed
fix: lazy-load CLI execution helpers
1 parent 0e679e2 commit e59a2b1

2 files changed

Lines changed: 67 additions & 2 deletions

File tree

src/browser_harness/run.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,25 @@
2222
stop_remote_daemon,
2323
sync_local_profile,
2424
)
25-
from .helpers import *
25+
26+
27+
def _execution_globals():
28+
"""Globals for `-c` snippets, with helpers loaded only for execution.
29+
30+
Maintenance commands like --version and --help must not import
31+
BH_AGENT_WORKSPACE/agent_helpers.py. That file is user-editable and can have
32+
arbitrary side effects, so keep it out of the CLI control path and expose it
33+
only to snippets that explicitly execute with `browser-harness -c ...`.
34+
"""
35+
from . import helpers
36+
37+
namespace = dict(globals())
38+
namespace.update(
39+
(name, value)
40+
for name, value in vars(helpers).items()
41+
if not name.startswith("_")
42+
)
43+
return namespace
2644

2745
HELP = """Browser Harness
2846
@@ -103,7 +121,7 @@ def main():
103121
):
104122
start_remote_daemon(NAME)
105123
ensure_daemon()
106-
exec(args[1], globals())
124+
exec(args[1], _execution_globals())
107125

108126

109127
if __name__ == "__main__":

tests/unit/test_run.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,57 @@
1+
import os
2+
import subprocess
13
import sys
24
from io import StringIO
5+
from pathlib import Path
36
from unittest.mock import patch
47

58
from browser_harness import run
69

710

11+
def test_maintenance_commands_do_not_load_agent_helpers(tmp_path):
12+
(tmp_path / "agent_helpers.py").write_text(
13+
"raise RuntimeError('agent_helpers should not load for maintenance commands')\n"
14+
)
15+
repo_root = Path(__file__).resolve().parents[2]
16+
env = os.environ.copy()
17+
env["BH_AGENT_WORKSPACE"] = str(tmp_path)
18+
env["PYTHONPATH"] = os.pathsep.join(
19+
[str(repo_root / "src"), env.get("PYTHONPATH", "")]
20+
)
21+
22+
for arg in ("--version", "--help"):
23+
result = subprocess.run(
24+
[sys.executable, "-m", "browser_harness.run", arg],
25+
cwd=repo_root,
26+
env=env,
27+
text=True,
28+
capture_output=True,
29+
timeout=10,
30+
)
31+
assert result.returncode == 0, result.stderr
32+
assert "agent_helpers should not load" not in result.stderr
33+
34+
35+
def test_execution_globals_load_agent_workspace_helpers(tmp_path, monkeypatch):
36+
import browser_harness
37+
38+
(tmp_path / "agent_helpers.py").write_text("CUSTOM_AGENT_HELPER = 'loaded'\n")
39+
monkeypatch.setenv("BH_AGENT_WORKSPACE", str(tmp_path))
40+
original_helpers = sys.modules.pop("browser_harness.helpers", None)
41+
original_package_helper = getattr(browser_harness, "helpers", None)
42+
if hasattr(browser_harness, "helpers"):
43+
delattr(browser_harness, "helpers")
44+
try:
45+
namespace = run._execution_globals()
46+
assert namespace["CUSTOM_AGENT_HELPER"] == "loaded"
47+
finally:
48+
sys.modules.pop("browser_harness.helpers", None)
49+
if original_helpers is not None:
50+
sys.modules["browser_harness.helpers"] = original_helpers
51+
if original_package_helper is not None:
52+
browser_harness.helpers = original_package_helper
53+
54+
855
def test_c_flag_executes_code():
956
stdout = StringIO()
1057
with patch.object(sys, "argv", ["browser-harness", "-c", "print('hello from -c')"]), \

0 commit comments

Comments
 (0)