1
0
mirror of https://github.com/kevin1024/vcrpy.git synced 2025-12-08 16:53:23 +00:00

feat: add an option to exclude unused interactions

Introduce the `drop_unused_requests` option (False by default). If True, it will force the `Cassette` saving operation with only played old interactions and new ones if they exist. As a result, unused old requests are dropped.

Add `_old_interactions`, `_played_interactions` and `_new_interactions()`.  The `_old_interactions` are previously recorded interactions loaded from Cassette files. The `_played_interactions` is a set of old interactions that were marked as played.  A new interaction is a tuple (request, response) in `self.data` that is not in `_old_interactions` list.
This commit is contained in:
Daniel Silva
2023-01-02 03:52:52 +00:00
parent 42d79b1102
commit 99c0384770
2 changed files with 29 additions and 1 deletions

View File

@@ -197,6 +197,7 @@ class Cassette:
custom_patches=(),
inject=False,
allow_playback_repeats=False,
drop_unused_requests=False,
):
self._persister = persister or FilesystemPersister
self._path = path
@@ -209,6 +210,7 @@ class Cassette:
self.record_mode = record_mode
self.custom_patches = custom_patches
self.allow_playback_repeats = allow_playback_repeats
self.drop_unused_requests = drop_unused_requests
# self.data is the list of (req, resp) tuples
self.data = []
@@ -216,6 +218,10 @@ class Cassette:
self.dirty = False
self.rewound = False
# Subsets of self.data to store old and played interactions
self._old_interactions = []
self._played_interactions = []
@property
def play_count(self):
return sum(self.play_counts.values())
@@ -277,6 +283,7 @@ class Cassette:
for index, response in self._responses(request):
if self.play_counts[index] == 0 or self.allow_playback_repeats:
self.play_counts[index] += 1
self._played_interactions.append((request, response))
return response
# The cassette doesn't contain the request asked for.
raise UnhandledHTTPRequestError(
@@ -337,10 +344,27 @@ class Cassette:
return final_best_matches
def _new_interactions(self):
"""List of new HTTP interactions (request/response tuples)"""
new_interactions = []
for request, response in self.data:
if all(not requests_match(request, old_request, self._match_on)
for old_request, _ in self._old_interactions):
new_interactions.append((request, response))
return new_interactions
def _as_dict(self):
return {"requests": self.requests, "responses": self.responses}
requests = self.requests
responses = self.responses
if self.drop_unused_requests:
interactions = self._played_interactions + self._new_interactions()
requests = [request for request, _ in interactions]
responses = [response for _, response in interactions]
return {"requests": requests, "responses": responses}
def _save(self, force=False):
if (len(self._played_interactions) < len(self._old_interactions)):
force = True
if force or self.dirty:
self._persister.save_cassette(self._path, self._as_dict(), serializer=self._serializer)
self.dirty = False
@@ -350,6 +374,7 @@ class Cassette:
requests, responses = self._persister.load_cassette(self._path, serializer=self._serializer)
for request, response in zip(requests, responses):
self.append(request, response)
self._old_interactions.append((request, response))
self.dirty = False
self.rewound = True
except ValueError:

View File

@@ -50,6 +50,7 @@ class VCR:
func_path_generator=None,
decode_compressed_response=False,
record_on_exception=True,
drop_unused_requests=False,
):
self.serializer = serializer
self.match_on = match_on
@@ -83,6 +84,7 @@ class VCR:
self.decode_compressed_response = decode_compressed_response
self.record_on_exception = record_on_exception
self._custom_patches = tuple(custom_patches)
self.drop_unused_requests = drop_unused_requests
def _get_serializer(self, serializer_name):
try:
@@ -153,6 +155,7 @@ class VCR:
"func_path_generator": func_path_generator,
"allow_playback_repeats": kwargs.get("allow_playback_repeats", False),
"record_on_exception": record_on_exception,
"drop_unused_requests": kwargs.get("drop_unused_requests", self.drop_unused_requests),
}
path = kwargs.get("path")
if path: