What's Changed
New features
Cassette metadata (#934, thanks @hasier): store values that aren't part of an interaction, such as a seed for random IDs a test sends, so they're the same when a cassette is recorded and played back.
with my_vcr.use_cassette("test.yaml") as cass:
seed = cass.get_metadata("seed", random.getrandbits(128))The cassette stores default the first time and returns the stored value after that. If the record mode doesn't allow changing the cassette, a missing key raises MissingMetadataError, a CannotOverwriteExistingCassetteException. See the docs.
skip_patchers (#944, #1070, thanks @smoltafet): leave some HTTP libraries unpatched. For example, skip_patchers=["httpx"] stops an httpx client with an aiohttp transport (httpx-aiohttp) from being recorded twice.
filter_nested_post_data_parameters (#936, #937, thanks @tighwm and @JargeZ): make filter_post_data_parameters also filter keys in nested objects of JSON request bodies, such as JSON-RPC params. It's opt-in, so existing setups don't filter more than before.
ignore_hosts accepts compiled regular expressions (#779, thanks @silviumarcu), which match whole host names: ignore_hosts=["example.com", re.compile(r".*\.actions\.githubusercontent\.com")].
allow_playback_repeats also applies while recording (#878, #879, thanks @pyoor): a request that matches one already recorded gets the recorded response, instead of being sent and recorded again. When played back, such requests got the first response anyway.
Fixes
- An empty cassette file is recorded like a missing one, instead of crashing with
TypeErrororJSONDecodeError(#579, #1081, thanks @nk-batman21) - aiohttp: requests that aren't recorded, e.g. with
ignore_localhostorignore_hosts, no longer have their response body read by vcrpy, so they stream as usual (#978, thanks @AronsonDan) - urllib3:
release_conn()on a streamed response returns its connection to the pool (#1084, thanks @edsonsims) drop_unused_requestsno longer saves an interaction once per playback whenallow_playback_repeatsis set
Docs and CI
before_record_responsealso runs when a cassette is loaded, so it should be idempotent (#1042, #1044, thanks @ciastek)- Examples use
urllib.requestinstead of Python 2'surllib2(#998, thanks @TejasAmle) - CI: pre-commit runs on Node.js 24 (#1072, thanks @pylaterreur), ruff 0.17.2 (#1083), Sphinx 9 (#1082)
Full Changelog: v9.2.0...v9.3.0