Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nesting CassetteContextDecorators does not work properly #107

Closed
colonelpanic8 opened this issue Sep 18, 2014 · 2 comments
Closed

Nesting CassetteContextDecorators does not work properly #107

colonelpanic8 opened this issue Sep 18, 2014 · 2 comments

Comments

@colonelpanic8
Copy link
Collaborator

Nesting any use of CassetteContextDecorators will result in complete unpatching after the first context is exited. This is because the reset function in patch.py indiscriminately sets all the patches back to the original state that was found in the module at import time.

Patching is a pretty tricky problem and I think that doing it by hand amounts to reinventing the wheel in some sense. I think that the best way to fix this issue is to rely on the mock library to do all of the patching.

Here are two tests that illustrate the problem:

@mock.patch('vcr.cassette.requests_match', _mock_requests_match)
@mock.patch('vcr.cassette.Cassette.can_play_response_for', return_value=True)
@mock.patch('vcr.cassette.Cassette._save', return_value=True)
def test_nesting_cassette_context_managers(*args):
    first_response = {'body': {'string': b'first_response'}, 'headers': {},
                      'status': {'message': 'm', 'code': 200}}

    second_response = copy.deepcopy(first_response)
    second_response['body']['string'] = b'second_response'

    with Cassette.use('test') as first_cassette, \
        mock.patch.object(first_cassette, 'play_response', return_value=first_response):
        assert_get_response_body_is('first_response')

        # Make sure a second cassette can supercede the first
        with Cassette.use('test') as second_cassette, \
        mock.patch.object(second_cassette, 'play_response', return_value=second_response):
            assert_get_response_body_is('second_response')

        # Now the first cassette should be back in effect
        assert_get_response_body_is('first_response')


def test_nesting_context_managers_by_checking_references_of_http_connection():
    with Cassette.use('test'):
        first_cassette_HTTPConnection = httplib.HTTPConnection
        with Cassette.use('test'):
            pass
        assert httplib.HTTPConnection is first_cassette_HTTPConnection

and here is the output that they produce:
https://gist.github.com/anonymous/f51bdd0334ee5fdb33bc

@colonelpanic8
Copy link
Collaborator Author

is it a problem that I use the multiple context manage with block syntax here? That wasn't available until python 2.7.

I think we should maybe add contextlib2 as a dependency so that we can have a good way to enter multiple context manager.

@colonelpanic8
Copy link
Collaborator Author

This was fixed by #108.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant