1
0
mirror of https://github.com/kevin1024/vcrpy.git synced 2025-12-10 01:25:34 +00:00

add allow_playback_repeats option to Cassette

This commit is contained in:
Tyson Holub
2020-07-02 10:10:49 -04:00
committed by Kevin McCarthy
parent a249781b97
commit 042ee790e2
4 changed files with 49 additions and 3 deletions

View File

@@ -33,6 +33,8 @@ consider part of the API. The fields are as follows:
been played back. been played back.
- ``responses_of(request)``: Access the responses that match a given - ``responses_of(request)``: Access the responses that match a given
request request
- ``allow_playback_repeats``: A boolean indicating whether responses
can be played back more than once.
The ``Request`` object has the following properties: The ``Request`` object has the following properties:
@@ -386,3 +388,19 @@ VCR.py allows to rewind a cassette in order to replay it inside the same functio
assert cass.all_played assert cass.all_played
cass.rewind() cass.rewind()
assert not cass.all_played assert not cass.all_played
Playback Repeats
----------------
By default, each response in a cassette can only be matched and played back
once while the cassette is in use, unless the cassette is rewound.
If you want to allow playback repeats without rewinding the cassette, use
the Cassette ``allow_playback_repeats`` option.
.. code:: python
with vcr.use_cassette('fixtures/vcr_cassettes/synopsis.yaml', allow_playback_repeats=True) as cass:
for x in range(10):
response = urllib2.urlopen('http://www.zombo.com/').read()
assert cass.all_played

View File

@@ -137,6 +137,31 @@ def test_cassette_all_played():
assert a.all_played assert a.all_played
@mock.patch("vcr.cassette.requests_match", _mock_requests_match)
def test_cassette_allow_playback_repeats():
a = Cassette("test", allow_playback_repeats=True)
a.append("foo", "bar")
a.append("other", "resp")
for x in range(10):
assert a.play_response("foo") == "bar"
assert a.play_count == 10
assert a.all_played is False
assert a.play_response("other") == "resp"
assert a.play_count == 11
assert a.all_played
a.allow_playback_repeats = False
with pytest.raises(UnhandledHTTPRequestError) as e:
a.play_response("foo")
assert str(e.value) == "\"The cassette ('test') doesn't contain the request ('foo') asked for\""
a.rewind()
assert a.all_played is False
assert a.play_response("foo") == "bar"
assert a.all_played is False
assert a.play_response("other") == "resp"
assert a.all_played
@mock.patch("vcr.cassette.requests_match", _mock_requests_match) @mock.patch("vcr.cassette.requests_match", _mock_requests_match)
def test_cassette_rewound(): def test_cassette_rewound():
a = Cassette("test") a = Cassette("test")

View File

@@ -182,6 +182,7 @@ class Cassette:
before_record_response=None, before_record_response=None,
custom_patches=(), custom_patches=(),
inject=False, inject=False,
allow_playback_repeats=False,
): ):
self._persister = persister or FilesystemPersister self._persister = persister or FilesystemPersister
self._path = path self._path = path
@@ -193,6 +194,7 @@ class Cassette:
self.inject = inject self.inject = inject
self.record_mode = record_mode self.record_mode = record_mode
self.custom_patches = custom_patches self.custom_patches = custom_patches
self.allow_playback_repeats = allow_playback_repeats
# self.data is the list of (req, resp) tuples # self.data is the list of (req, resp) tuples
self.data = [] self.data = []
@@ -207,7 +209,7 @@ class Cassette:
@property @property
def all_played(self): def all_played(self):
"""Returns True if all responses have been played, False otherwise.""" """Returns True if all responses have been played, False otherwise."""
return self.play_count == len(self) return len(self.play_counts.values()) == len(self)
@property @property
def requests(self): def requests(self):
@@ -259,7 +261,7 @@ class Cassette:
hasn't been played back before, and mark it as played hasn't been played back before, and mark it as played
""" """
for index, response in self._responses(request): for index, response in self._responses(request):
if self.play_counts[index] == 0: if self.play_counts[index] == 0 or self.allow_playback_repeats:
self.play_counts[index] += 1 self.play_counts[index] += 1
return response return response
# The cassette doesn't contain the request asked for. # The cassette doesn't contain the request asked for.
@@ -349,6 +351,6 @@ class Cassette:
def __contains__(self, request): def __contains__(self, request):
"""Return whether or not a request has been stored""" """Return whether or not a request has been stored"""
for index, response in self._responses(request): for index, response in self._responses(request):
if self.play_counts[index] == 0: if self.play_counts[index] == 0 or self.allow_playback_repeats:
return True return True
return False return False

View File

@@ -149,6 +149,7 @@ class VCR:
"inject": kwargs.get("inject_cassette", self.inject_cassette), "inject": kwargs.get("inject_cassette", self.inject_cassette),
"path_transformer": path_transformer, "path_transformer": path_transformer,
"func_path_generator": func_path_generator, "func_path_generator": func_path_generator,
"allow_playback_repeats": kwargs.get("allow_playback_repeats", False),
} }
path = kwargs.get("path") path = kwargs.get("path")
if path: if path: