Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions tests/test_live_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,30 @@ def test_a_runner_started_by_a_launcher_counts_as_a_verification(cmd):
assert g.verifications == 1 and not g.resolved_proxy()


@pytest.mark.parametrize("cmd", ["env -u CURSOR_AGENT python -m pytest tests",
"env -i PATH=/usr/bin go test ./...", "env --unset=CI npm test",
"env -C web npx vitest run", "nice -n 10 pytest -q",
"nice -n10 cargo test", "nice -5 go test ./...",
"FOO=1 env -u X timeout 60 npm test"])
def test_a_runner_behind_env_or_nice_options_counts_as_a_verification(cmd):
"""`env -u VAR` and `nice -n 10` take options before the command they run. Only the bare
word was passed over, so the run was no verification and a failing one after the last edit
left the turn green."""
assert turn.status_of_tests(cmd) == "own"
g = guard.TurnGuard(turn_key="t")
g.fold("Edit", {"file_path": "/r/a.py", "old_string": "x", "new_string": "y"}, "ok")
g.fold("Bash", {"command": cmd}, "FAILED (failures=1)", 1)
assert g.verifications == 1 and not g.resolved_proxy()


@pytest.mark.parametrize("cmd,status", [("env -u CI python -m pytest --collect-only", None),
("env -u CI echo pytest", None),
("nice -n 10 make", None), ("env pytest", "own"),
("nice pytest -q", "own")])
def test_env_and_nice_leave_what_they_run_to_decide(cmd, status):
assert turn.status_of_tests(cmd) == status


@pytest.mark.parametrize("cmd,status", [("uv run ruff check", None),
("npx prettier --check .", None),
("pnpm exec jest --help", None),
Expand Down
10 changes: 7 additions & 3 deletions tokeneconomizer/loopguard/turn.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@
_SEP_RE = re.compile(r"(&&|\|\||\|&|(?<!>)\||;|\n)") # `|`, but not the `>|` redirect
# A runner asked for its help, version or test list, not to run the tests.
_NOT_A_RUN_RE = re.compile(r"\s(?:-h|--help|--version|--collect-only|--co|--list\S*)(?!\S)")
# What may precede the command itself: `FOO=1 timeout 60 npm test`, and a launcher that runs
# it in the project's environment, `uv run pytest`, `npx jest`, `bundle exec rspec`.
_PREFIX_RE = re.compile(r"^\s*(?:(?:\w+=\S*|time|nice|nohup|command|env|"
# What may precede the command itself: `FOO=1 timeout 60 npm test`, `env -u VAR`, `nice -n 10`,
# and a launcher that runs it in the project's environment, `uv run pytest`, `npx jest`,
# `bundle exec rspec`.
_PREFIX_RE = re.compile(r"^\s*(?:(?:\w+=\S*|time|nohup|command|"
r"nice(?:\s+(?:-n\s*|--adjustment=)?[-+]?\d+)?|"
# env's options; `-u`, `-C` and their long forms take a value
r"env(?:\s+(?:(?:-[uC]|--unset|--chdir)(?:=|\s*)[^\s-]\S*|-[-\w]*))*|"
r"timeout(?:\s+(?:-\S+|[A-Z]+|\d\S*))+|"
r"(?:(?:uv|poetry|pipenv|pdm|hatch|rye)\s+run|npx|bunx|"
r"(?:npm|pnpm|yarn)\s+(?:exec|dlx)|bundle\s+exec|xvfb-run)"
Expand Down