fix(tests): confine os patches to the module under test

`some_module.os` is the shared os module, so patching an attribute through
it installs the replacement for every importer in the process. That is held
together only by teardown ordering, which a test does not control: any
pytest_runtest_ hook touching the filesystem runs before fixture finalizers,
meets the replacement, and -- when the replacement raises, as most of these
do -- takes the teardown chain with it, after which the undo never happens.
One such test produced ~3000 cascading errors from ~40% of a run onward.

All 14 sites now go through patch_module_os, which swaps the module's
reference rather than the module's contents, and a grep gate keeps the
pattern from coming back.

Closes #1123
This commit is contained in:
Haozhe Wu committed 2026-08-18 15:20:42 +08:00
1 parent b22c974e47
commit 0b05671be1
9 files changed
+148 -14

No files matched your search

+19
View File
@@ -143,6 +143,25 @@ else
echo "${GREEN}ok${NC}"
fi
# -------------------------------------------------------------- gate (f)
# `some_module.os` IS the shared os module, so patching an attribute through it
# reaches every importer in the process. pytest's own teardown calls os.scandir
# and os.replace while fixture finalizers are still pending, so a replacement
# that raises aborts the teardown chain and its undo never runs (#1123 -- one
# such test produced ~3000 cascading errors). Patch the module's REFERENCE
# instead: tests/module_os_helpers.py::patch_module_os.
echo "[gate f] no process-wide os patches in tests ..."
F_OUTPUT=$(grep -rn "setattr([a-zA-Z_][a-zA-Z_0-9]*\.os," agent/tests --include="*.py" \
| grep -v "^agent/tests/module_os_helpers.py:" || true)
if [ -n "$F_OUTPUT" ]; then
echo "${RED}FAIL${NC}: patch the module's os reference, not the shared os module:"
echo "$F_OUTPUT"
echo " use: from tests.module_os_helpers import patch_module_os"
FAILED=1
else
echo "${GREEN}ok${NC}"
fi
# --------------------------------------------------------------- result
if [ "$FAILED" -ne 0 ]; then
echo