From 3c3293d739b54ce3feb4c2808ef70014f82dc22d Mon Sep 17 00:00:00 2001 From: Miroslav Shubernetskiy Date: Tue, 27 Sep 2022 11:53:03 -0400 Subject: [PATCH 1/2] disallowing writes only when fully matched request is in cassette `cassette.filter_request` only filters some request attributes like headers but does not take into account any of the `match_on` configurations. As a result if a similar request has been seen before but does not fully match as per `match_on`, writes will be disallowed. `cassette.__contains__` however fully takes into account all `match_on` matchers and therefore will only guard against recording to the cassette when the same request has been previously recorded --- vcr/stubs/__init__.py | 2 +- vcr/stubs/aiohttp_stubs.py | 2 +- vcr/stubs/httpx_stubs.py | 2 +- vcr/stubs/tornado_stubs.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vcr/stubs/__init__.py b/vcr/stubs/__init__.py index 8a1a16a47..ce3a501a0 100644 --- a/vcr/stubs/__init__.py +++ b/vcr/stubs/__init__.py @@ -227,7 +227,7 @@ def getresponse(self, _=False, **kwargs): response = self.cassette.play_response(self._vcr_request) return VCRHTTPResponse(response) else: - if self.cassette.write_protected and self.cassette.filter_request(self._vcr_request): + if self.cassette.write_protected and self._vcr_request in self.cassette: raise CannotOverwriteExistingCassetteException( cassette=self.cassette, failed_request=self._vcr_request ) diff --git a/vcr/stubs/aiohttp_stubs.py b/vcr/stubs/aiohttp_stubs.py index f71b1394c..3fbda8603 100644 --- a/vcr/stubs/aiohttp_stubs.py +++ b/vcr/stubs/aiohttp_stubs.py @@ -269,7 +269,7 @@ async def new_request(self, method, url, **kwargs): self._cookie_jar.update_cookies(response.cookies, response.url) return response - if cassette.write_protected and cassette.filter_request(vcr_request): + if cassette.write_protected and vcr_request in cassette: raise CannotOverwriteExistingCassetteException(cassette=cassette, failed_request=vcr_request) log.info("%s not in cassette, sending to real server", vcr_request) diff --git a/vcr/stubs/httpx_stubs.py b/vcr/stubs/httpx_stubs.py index 803ddbe15..b31043399 100644 --- a/vcr/stubs/httpx_stubs.py +++ b/vcr/stubs/httpx_stubs.py @@ -83,7 +83,7 @@ def _shared_vcr_send(cassette, real_send, *args, **kwargs): if cassette.can_play_response_for(vcr_request): return vcr_request, _play_responses(cassette, real_request, vcr_request, args[0], kwargs) - if cassette.write_protected and cassette.filter_request(vcr_request): + if cassette.write_protected and vcr_request in cassette: raise CannotOverwriteExistingCassetteException(cassette=cassette, failed_request=vcr_request) _logger.info("%s not in cassette, sending to real server", vcr_request) diff --git a/vcr/stubs/tornado_stubs.py b/vcr/stubs/tornado_stubs.py index b482fd1f3..7255888b3 100644 --- a/vcr/stubs/tornado_stubs.py +++ b/vcr/stubs/tornado_stubs.py @@ -60,7 +60,7 @@ def new_fetch_impl(self, request, callback): ) return callback(response) else: - if cassette.write_protected and cassette.filter_request(vcr_request): + if cassette.write_protected and vcr_request in cassette: response = HTTPResponse( request, 599, From 62ce106cda3ee9b543ee59f7f454e54ac1617432 Mon Sep 17 00:00:00 2001 From: Miroslav Shubernetskiy Date: Fri, 21 Oct 2022 14:40:41 -0400 Subject: [PATCH 2/2] do not match ignored requests assuming: * any of the ignore requests is configured as documented in https://vcrpy.readthedocs.io/en/latest/advanced.html?highlight=ignore_hosts#ignore-requests * request matchers are configured as documented in https://vcrpy.readthedocs.io/en/latest/configuration.html#request-matching since the filtering logic returns None when request should be ignored however matchers assume both requests being compared are valid requests and so when one of the requests is None it raises AttributeError as no attribute such as "uri" can be accessed on NoneType this fix simply does not consider the request for matching if it is ignored --- vcr/cassette.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vcr/cassette.py b/vcr/cassette.py index 9122b4aa0..0db985690 100644 --- a/vcr/cassette.py +++ b/vcr/cassette.py @@ -247,6 +247,8 @@ def _responses(self, request): the request. """ request = self._before_record_request(request) + if request is None: + return for index, (stored_request, response) in enumerate(self.data): if requests_match(request, stored_request, self._match_on): yield index, response