diff --git a/tests/unit/test_cassettes.py b/tests/unit/test_cassettes.py index b612072..1b310c4 100644 --- a/tests/unit/test_cassettes.py +++ b/tests/unit/test_cassettes.py @@ -68,6 +68,22 @@ def test_cassette_cant_read_same_request_twice(): a.play_response('foo') +@mock.patch('vcr.cassette.requests_match', return_value=True) +@mock.patch('vcr.cassette.load_cassette', lambda *args, **kwargs: (('foo',), (mock.MagicMock(),))) +@mock.patch('vcr.cassette.Cassette.can_play_response_for', return_value=True) +@mock.patch('vcr.stubs.VCRHTTPResponse') +def test_function_decorated_with_use_cassette_can_be_invoked_multiple_times(*args): + from six.moves import http_client as httplib + @Cassette.use_cassette('test') + def decorated_function(): + conn = httplib.HTTPConnection("www.python.org") + conn.request("GET", "/index.html") + conn.getresponse() + + for i in range(2): + decorated_function() + + def test_cassette_not_all_played(): a = Cassette('test') a.append('foo', 'bar') diff --git a/vcr/cassette.py b/vcr/cassette.py index 36deed3..fb3c77c 100644 --- a/vcr/cassette.py +++ b/vcr/cassette.py @@ -1,12 +1,10 @@ '''The container for recorded requests and responses''' - +import functools try: from collections import Counter except ImportError: from .compat.counter import Counter -from contextdecorator import ContextDecorator - # Internal imports from .patch import install, reset from .persist import load_cassette, save_cassette @@ -16,7 +14,29 @@ from .matchers import requests_match, uri, method from .errors import UnhandledHTTPRequestError -class Cassette(ContextDecorator): +class use_cassette(object): + + def __init__(self, cls, *args, **kwargs): + self.args = args + self.kwargs = kwargs + self.cls = cls + + def __enter__(self): + self._cassette = self.cls.load(*self.args, **self.kwargs) + return self._cassette.__enter__() + + def __exit__(self, *args): + return self._cassette.__exit__(*args) + + def __call__(self, function): + @functools.wraps(function) + def wrapped(*args, **kwargs): + with self: + return function(*args, **kwargs) + return wrapped + + +class Cassette(object): '''A container for recorded requests and responses''' @classmethod @@ -26,6 +46,10 @@ class Cassette(ContextDecorator): new_cassette._load() return new_cassette + @classmethod + def use_cassette(cls, *args, **kwargs): + return use_cassette(cls, *args, **kwargs) + def __init__(self, path, serializer=yamlserializer, diff --git a/vcr/config.py b/vcr/config.py index 0a1615a..1b868cd 100644 --- a/vcr/config.py +++ b/vcr/config.py @@ -103,7 +103,7 @@ class VCR(object): ), } - return Cassette.load(path, **merged_config) + return Cassette.use_cassette(path, **merged_config) def register_serializer(self, name, serializer): self.serializers[name] = serializer