mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-09 09:13:23 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b7e6c0ab8 | ||
|
|
bd7c6ed03f | ||
|
|
1e414826e7 | ||
|
|
1e1c093b3c | ||
|
|
bb8f563135 | ||
|
|
ca3200d96e | ||
|
|
04b5978adc | ||
|
|
01f1f9fdc1 | ||
|
|
a82e8628c2 | ||
|
|
7d68f0577a |
@@ -608,6 +608,8 @@ new API in version 1.0.x
|
||||
|
||||
Changelog
|
||||
---------
|
||||
- 1.7.2 [#186] Get effective_url in tornado (thanks @mvschaik), [#187]
|
||||
Set request_time on Response object in tornado (thanks @abhinav).
|
||||
- 1.7.1 [#183] Patch ``fetch_impl`` instead of the entire HTTPClient
|
||||
class for Tornado (thanks @abhinav).
|
||||
- 1.7.0 [#177] Properly support coroutine/generator decoration. [#178]
|
||||
|
||||
2
setup.py
2
setup.py
@@ -51,7 +51,7 @@ except Exception:
|
||||
|
||||
setup(
|
||||
name='vcrpy',
|
||||
version='1.7.1',
|
||||
version='1.7.2',
|
||||
description=(
|
||||
"Automatically mock your HTTP interactions to simplify and "
|
||||
"speed up testing"
|
||||
|
||||
@@ -56,6 +56,17 @@ def test_response_headers(scheme, tmpdir):
|
||||
resp, _ = httplib2.Http().request(url)
|
||||
assert set(headers) == set(resp.items())
|
||||
|
||||
def test_effective_url(scheme, tmpdir):
|
||||
'''Ensure that the effective_url is captured'''
|
||||
url = scheme + '://httpbin.org/redirect-to?url=/html'
|
||||
with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass:
|
||||
resp, _ = httplib2.Http().request(url)
|
||||
effective_url = resp['content-location']
|
||||
assert effective_url == scheme + '://httpbin.org/html'
|
||||
|
||||
with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass:
|
||||
resp, _ = httplib2.Http().request(url)
|
||||
assert effective_url == resp['content-location']
|
||||
|
||||
def test_multiple_requests(scheme, tmpdir):
|
||||
'''Ensure that we can cache multiple requests'''
|
||||
|
||||
@@ -44,6 +44,15 @@ def test_body(tmpdir, scheme):
|
||||
with vcr.use_cassette(str(tmpdir.join('body.yaml'))):
|
||||
assert content == requests.get(url).content
|
||||
|
||||
def test_effective_url(scheme, tmpdir):
|
||||
'''Ensure that the effective_url is captured'''
|
||||
url = scheme + '://httpbin.org/redirect-to?url=/html'
|
||||
with vcr.use_cassette(str(tmpdir.join('url.yaml'))):
|
||||
effective_url = requests.get(url).url
|
||||
assert effective_url == scheme + '://httpbin.org/html'
|
||||
|
||||
with vcr.use_cassette(str(tmpdir.join('url.yaml'))):
|
||||
assert effective_url == requests.get(url).url
|
||||
|
||||
def test_auth(tmpdir, scheme):
|
||||
'''Ensure that we can handle basic auth'''
|
||||
|
||||
@@ -81,6 +81,17 @@ def test_body(get_client, tmpdir, scheme):
|
||||
assert content == (yield get(get_client(), url)).body
|
||||
assert 1 == cass.play_count
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_effective_url(get_client, scheme, tmpdir):
|
||||
'''Ensure that the effective_url is captured'''
|
||||
url = scheme + '://httpbin.org/redirect-to?url=/html'
|
||||
with vcr.use_cassette(str(tmpdir.join('url.yaml'))):
|
||||
effective_url = (yield get(get_client(), url)).effective_url
|
||||
assert effective_url == scheme + '://httpbin.org/html'
|
||||
|
||||
with vcr.use_cassette(str(tmpdir.join('url.yaml'))) as cass:
|
||||
assert effective_url == (yield get(get_client(), url)).effective_url
|
||||
assert 1 == cass.play_count
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_auth(get_client, tmpdir, scheme):
|
||||
@@ -326,3 +337,19 @@ def test_existing_instances_get_patched(get_client, tmpdir):
|
||||
with vcr.use_cassette(str(tmpdir.join('data.yaml'))) as cass:
|
||||
yield get(client, 'http://httpbin.org/get')
|
||||
assert cass.play_count == 1
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_request_time_is_set(get_client, tmpdir):
|
||||
'''Ensures that the request_time on HTTPResponses is set.'''
|
||||
|
||||
with vcr.use_cassette(str(tmpdir.join('data.yaml'))):
|
||||
client = get_client()
|
||||
response = yield get(client, 'http://httpbin.org/get')
|
||||
assert response.request_time is not None
|
||||
|
||||
with vcr.use_cassette(str(tmpdir.join('data.yaml'))) as cass:
|
||||
client = get_client()
|
||||
response = yield get(client, 'http://httpbin.org/get')
|
||||
assert response.request_time is not None
|
||||
assert cass.play_count == 1
|
||||
|
||||
@@ -49,6 +49,15 @@ def test_response_headers(scheme, tmpdir):
|
||||
open2 = urlopen(url).info().items()
|
||||
assert sorted(open1) == sorted(open2)
|
||||
|
||||
def test_effective_url(scheme, tmpdir):
|
||||
'''Ensure that the effective_url is captured'''
|
||||
url = scheme + '://httpbin.org/redirect-to?url=/html'
|
||||
with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass:
|
||||
effective_url = urlopen(url).geturl()
|
||||
assert effective_url == scheme + '://httpbin.org/html'
|
||||
|
||||
with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass:
|
||||
assert effective_url == urlopen(url).geturl()
|
||||
|
||||
def test_multiple_requests(scheme, tmpdir):
|
||||
'''Ensure that we can cache multiple requests'''
|
||||
|
||||
@@ -20,10 +20,18 @@ class CassetteContextDecorator(object):
|
||||
"""Context manager/decorator that handles installing the cassette and
|
||||
removing cassettes.
|
||||
|
||||
This class defers the creation of a new cassette instance until the point at
|
||||
which it is installed by context manager or decorator. The fact that a new
|
||||
cassette is used with each application prevents the state of any cassette
|
||||
from interfering with another.
|
||||
This class defers the creation of a new cassette instance until
|
||||
the point at which it is installed by context manager or
|
||||
decorator. The fact that a new cassette is used with each
|
||||
application prevents the state of any cassette from interfering
|
||||
with another.
|
||||
|
||||
Instances of this class are NOT reentrant as context managers.
|
||||
However, functions that are decorated by
|
||||
``CassetteContextDecorator`` instances ARE reentrant. See the
|
||||
implementation of ``__call__`` on this class for more details.
|
||||
There is also a guard against attempts to reenter instances of
|
||||
this class as a context manager in ``__exit__``.
|
||||
"""
|
||||
|
||||
_non_cassette_arguments = ('path_transformer', 'func_path_generator')
|
||||
@@ -41,9 +49,14 @@ class CassetteContextDecorator(object):
|
||||
with contextlib.ExitStack() as exit_stack:
|
||||
for patcher in CassettePatcherBuilder(cassette).build():
|
||||
exit_stack.enter_context(patcher)
|
||||
log.debug('Entered context for cassette at {0}.'.format(cassette._path))
|
||||
log_format = '{action} context for cassette at {path}.'
|
||||
log.debug(log_format.format(
|
||||
action="Entering", path=cassette._path
|
||||
))
|
||||
yield cassette
|
||||
log.debug('Exiting context for cassette at {0}.'.format(cassette._path))
|
||||
log.debug(log_format.format(
|
||||
action="Exiting", path=cassette._path
|
||||
))
|
||||
# TODO(@IvanMalison): Hmmm. it kind of feels like this should be
|
||||
# somewhere else.
|
||||
cassette._save()
|
||||
@@ -78,7 +91,9 @@ class CassetteContextDecorator(object):
|
||||
# functions are reentrant. This is required for thread
|
||||
# safety and the correct operation of recursive functions.
|
||||
args_getter = self._build_args_getter_for_decorator(function)
|
||||
return type(self)(self.cls, args_getter)._execute_function(function, args, kwargs)
|
||||
return type(self)(self.cls, args_getter)._execute_function(
|
||||
function, args, kwargs
|
||||
)
|
||||
|
||||
def _execute_function(self, function, args, kwargs):
|
||||
if inspect.isgeneratorfunction(function):
|
||||
|
||||
@@ -36,6 +36,7 @@ def vcr_fetch_impl(cassette, real_fetch_impl):
|
||||
"that is not yet supported by VCR.py. Please make the "
|
||||
"request outside a VCR.py context." % repr(request)
|
||||
),
|
||||
request_time=self.io_loop.time() - request.start_time,
|
||||
)
|
||||
return callback(response)
|
||||
|
||||
@@ -62,6 +63,8 @@ def vcr_fetch_impl(cassette, real_fetch_impl):
|
||||
reason=vcr_response['status']['message'],
|
||||
headers=headers,
|
||||
buffer=BytesIO(vcr_response['body']['string']),
|
||||
effective_url=vcr_response.get('url'),
|
||||
request_time=self.io_loop.time() - request.start_time,
|
||||
)
|
||||
return callback(response)
|
||||
else:
|
||||
@@ -77,6 +80,7 @@ def vcr_fetch_impl(cassette, real_fetch_impl):
|
||||
"your current record mode (%r)."
|
||||
% (vcr_request, cassette._path, cassette.record_mode)
|
||||
),
|
||||
request_time=self.io_loop.time() - request.start_time,
|
||||
)
|
||||
return callback(response)
|
||||
|
||||
@@ -93,6 +97,7 @@ def vcr_fetch_impl(cassette, real_fetch_impl):
|
||||
},
|
||||
'headers': headers,
|
||||
'body': {'string': response.body},
|
||||
'url': response.effective_url,
|
||||
}
|
||||
cassette.append(vcr_request, vcr_response)
|
||||
return callback(response)
|
||||
|
||||
Reference in New Issue
Block a user