Repository navigation
fix(tests): run offline with only the runtime requirements (the guard moves into conftest) - #13
Merged
Merged
Conversation
A reviewer's sandbox installs `requirements.txt` and runs whatever `pytest` the
machine has. Our pytest.ini addopts passed `--disable-socket`, which only exists
when the `pytest-socket` plugin from requirements-dev.txt is installed, so on
that install pytest refused to start at all:
ERROR: usage: python -m pytest [options] [file_or_dir] [...]
python -m pytest: error: unrecognized arguments: --disable-socket
--allow-hosts=127.0.0.1,localhost,::1
Not one test ran. CI stayed green because it installs requirements-dev.txt, so
the review reported "still failing tests" on a commit whose suite was fine.
The offline guarantee is now stdlib code in conftest.py: `socket.connect`,
`connect_ex` and `getaddrinfo` are wrapped and refuse anything outside loopback
until a `network`-marked test lifts them. Deps: pytest-socket is gone, nothing in
pytest.ini needs a dev-only package.
Two things that fix alone would not have caught:
- the wrappers are re-asserted in pytest_runtest_setup, because pytest-socket's
per-test teardown restores the real `socket.connect` and had silently disarmed
the guard partway through the run (found by testing the guard, not the suite);
- `reviewer-path` in ci.yml installs runtime requirements + pytest only and runs
both `pytest` and `python -m pytest` with an empty $HOME, so this exact
configuration can never go untested again.
tests/test_offline_guard.py tests the mechanism: DNS and connect are both
refused for an unmarked test, loopback still works, the marker lifts the guard,
and a clobbered wrapper is put back. Verified with 275 tests passing on Python
3.13 with only requirements.txt + pytest, empty HOME, no .env, read-only
checkout; plus ruff and the 79% coverage floor on the dev install.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The Nov 6 review ran
pip install -r requirements.txtand thenpytest, and the whole run died before collecting a test:--disable-socketcomes from thepytest-socketplugin, which is inrequirements-dev.txtonly. On a runtime-only install pytest refuses to start.ci.ymlinstallsrequirements-dev.txt, which is why CI was green on a suite that a reviewer could not run. Reproduced locally in a venv withrequirements.txt+pytest, and it is fixed there: 275 passed, 13 deselected on Python 3.13, empty$HOME, no.env.What changed
conftest.py— the offline guard is now stdlib:socket.connect,connect_exandgetaddrinfoare wrapped and raiseOfflineViolationfor anything outside loopback unless the test carries thenetworkmarker. No plugin, no ini flag.pytest.ini—addopts = -m "not network". Nothing in it requires a dev-only package.requirements-dev.txt—pytest-socketremoved (unused now; supersedes chore(deps-dev): update pytest-socket requirement from >=0.7.1 to >=0.8.1 #11).tests/test_offline_guard.py(new) — tests the mechanism, not the promise: DNS and connect are both refused unmarked, loopback and local bind still work, the marker lifts the guard, a clobbered wrapper is re-asserted.ci.yml— new blockingreviewer-pathjob: runtime requirements +pytestonly, barepytestandpython -m pytest, empty$HOME, plus the guard tests. This configuration can no longer go untested.pytest.ini.The part that needed a second look
Wrapping
socket.connectwas not enough.pytest-socket's per-test teardown restores the real Cconnect, so with the plugin installed the guard was silently disarmed after the first test — the DNS wrapper survived, the connect wrapper did not. The wrappers are captured once and re-asserted inpytest_runtest_setup, and there is a test for exactly that. Proved the guard still bites by stripping thenetworkmarker off a live-calling test:OfflineViolation: blocked DNS lookup for 'api.x402.celo.org'.Verification
pytestonly, Py 3.13, empty HOME, no.envpytestfrom repo root--cov-fail-under=75ruff check .+compileall