test: fail loudly if cassette replay stops intercepting edgartools' HTTP stack (243z) - #1389
Merged
Merged
Conversation
…TTP stack (243z) vcrpy intercepts by patching httpcore's connection pools by name. When that stops matching the client -- an httpx or vcrpy upgrade, or the httpx2 swap -- a cassette test silently fetches from the network and passes while SEC answers. The q2iz spike measured it (vcrpy 8.1.1 + httpx2: 0 interactions, test green). tests/meta/test_vcr_interception_guard.py replays a cassette for 127.0.0.1:9 (the discard port, which no cache rule covers) with record_mode="none", through edgar.httprequests.get_with_retry and get_with_retry_async, so the throttle/cache layers above vcr are in the path. It asserts the body and cassette.play_count == 1, and that a request the cassette lacks is refused by vcr (CannotOverwriteExistingCassetteException), not sent. Verified by mutation: with vcr.patch.CassettePatcherBuilder._httpcore neutered, all 3 fail -- ConnectError normally, NetworkBlockedError under tests/_offline_harness. Unmutated, all 3 pass both ways, which is what the PR-gate offline audit requires. Deviation from the bead: no record guard against a local HTTP server. The offline audit blocks loopback too, so it would fail the PR gate as network-dependent; record and replay share the same httpcore patch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
What this changes
vcrpy intercepts by patching httpcore's connection pools by name. If an httpx or vcrpy upgrade, or the planned httpx2 swap, breaks that patching, every cassette test silently fetches from SEC and still passes. The q2iz spike measured exactly that: vcrpy 8.1.1 with httpx2 recorded 0 interactions and the test stayed green. Nothing in the suite noticed.
tests/meta/test_vcr_interception_guard.pyadds 3 fast tests. Each replays a cassette withrecord_mode="none"for127.0.0.1:9, a dead address that noCACHE_RULESentry covers, and goes through edgartools' ownget_with_retry/get_with_retry_async. That puts the throttle and cache layers above vcr in the path, as they are for every real test.cassette.play_count == 1CannotOverwriteExistingCassetteException), not sentThis is a 6.0 gate (bead edgartools-243z, decided 2026-09-30). It must land before 5.60.0 and ahead of the
edgar/filesdeletion.Verification
ConnectError: Connection refused)-p tests._offline_harnessNetworkBlockedError)The mutation replaced
vcr.patch.CassettePatcherBuilder._httpcorewith a no-op, which simulates lost interception. Unmutated, the module passes under the offline harness, so the PR gate's offline audit accepts it.tests/metahas 95 passing, and the guard also passes next totests/core/test_httprequests.pyand the #519 regression, both sequentially and with-n 3.Deviation from the bead
The bead also asked for a record guard against a local HTTP server. I left it out: the offline audit blocks loopback sockets too, so that test would fail the PR gate as network-dependent. Recording and replay go through the same httpcore patch, so losing one means losing the other.
🤖 Generated with Claude Code