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

Merge pull request #184 from abhinav/master

For Tornado AsyncHTTPClient, replace the methods instead of the class.
This commit is contained in:
Kevin McCarthy
2015-08-12 09:16:22 -10:00
3 changed files with 64 additions and 72 deletions

View File

@@ -298,3 +298,31 @@ def test_tornado_exception_can_be_caught(get_client):
yield get(get_client(), 'http://httpbin.org/status/404')
except http.HTTPError as e:
assert e.code == 404
@pytest.mark.gen_test
def test_existing_references_get_patched(tmpdir):
from tornado.httpclient import AsyncHTTPClient
with vcr.use_cassette(str(tmpdir.join('data.yaml'))):
client = AsyncHTTPClient()
yield get(client, 'http://httpbin.org/get')
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_existing_instances_get_patched(get_client, tmpdir):
'''Ensure that existing instances of AsyncHTTPClient get patched upon
entering VCR context.'''
client = get_client()
with vcr.use_cassette(str(tmpdir.join('data.yaml'))):
yield get(client, 'http://httpbin.org/get')
with vcr.use_cassette(str(tmpdir.join('data.yaml'))) as cass:
yield get(client, 'http://httpbin.org/get')
assert cass.play_count == 1

View File

@@ -54,13 +54,12 @@ else:
# Try to save the original types for Tornado
try:
import tornado.httpclient
import tornado.simple_httpclient
except ImportError: # pragma: no cover
pass
else:
_AsyncHTTPClient = tornado.httpclient.AsyncHTTPClient
_SimpleAsyncHTTPClient = tornado.simple_httpclient.SimpleAsyncHTTPClient
_SimpleAsyncHTTPClient_fetch_impl = \
tornado.simple_httpclient.SimpleAsyncHTTPClient.fetch_impl
try:
@@ -68,7 +67,8 @@ try:
except ImportError: # pragma: no cover
pass
else:
_CurlAsyncHTTPClient = tornado.curl_httpclient.CurlAsyncHTTPClient
_CurlAsyncHTTPClient_fetch_impl = \
tornado.curl_httpclient.CurlAsyncHTTPClient.fetch_impl
class CassettePatcherBuilder(object):
@@ -228,23 +228,27 @@ class CassettePatcherBuilder(object):
@_build_patchers_from_mock_triples_decorator
def _tornado(self):
try:
import tornado.httpclient as http
import tornado.simple_httpclient as simple
except ImportError: # pragma: no cover
pass
else:
from .stubs.tornado_stubs import VCRAsyncHTTPClient
from .stubs.tornado_stubs import VCRSimpleAsyncHTTPClient
from .stubs.tornado_stubs import vcr_fetch_impl
yield http, 'AsyncHTTPClient', VCRAsyncHTTPClient
yield simple, 'SimpleAsyncHTTPClient', VCRSimpleAsyncHTTPClient
new_fetch_impl = vcr_fetch_impl(
self._cassette, _SimpleAsyncHTTPClient_fetch_impl
)
yield simple.SimpleAsyncHTTPClient, 'fetch_impl', new_fetch_impl
try:
import tornado.curl_httpclient as curl
except ImportError: # pragma: no cover
pass
else:
from .stubs.tornado_stubs import VCRCurlAsyncHTTPClient
yield curl, 'CurlAsyncHTTPClient', VCRCurlAsyncHTTPClient
from .stubs.tornado_stubs import vcr_fetch_impl
new_fetch_impl = vcr_fetch_impl(
self._cassette, _CurlAsyncHTTPClient_fetch_impl
)
yield curl.CurlAsyncHTTPClient, 'fetch_impl', new_fetch_impl
def _urllib3_patchers(self, cpool, stubs):
http_connection_remover = ConnectionRemover(
@@ -362,19 +366,25 @@ def reset_patchers():
_CertValidatingHTTPSConnection)
try:
import tornado.httpclient as http
import tornado.simple_httpclient as simple
except ImportError: # pragma: no cover
pass
else:
yield mock.patch.object(http, 'AsyncHTTPClient', _AsyncHTTPClient)
yield mock.patch.object(simple, 'SimpleAsyncHTTPClient', _SimpleAsyncHTTPClient)
yield mock.patch.object(
simple.SimpleAsyncHTTPClient,
'fetch_impl',
_SimpleAsyncHTTPClient_fetch_impl,
)
try:
import tornado.curl_httpclient as curl
except ImportError: # pragma: no cover
pass
else:
yield mock.patch.object(curl, 'CurlAsyncHTTPClient', _CurlAsyncHTTPClient)
yield mock.patch.object(
curl.CurlAsyncHTTPClient,
'fetch_impl',
_CurlAsyncHTTPClient_fetch_impl,
)
@contextlib.contextmanager

View File

@@ -1,48 +1,20 @@
'''Stubs for tornado HTTP clients'''
from __future__ import absolute_import
import functools
from six import BytesIO
from tornado import httputil
from tornado.httpclient import AsyncHTTPClient
from tornado.httpclient import HTTPResponse
from tornado.simple_httpclient import SimpleAsyncHTTPClient
from vcr.errors import CannotOverwriteExistingCassetteException
from vcr.request import Request
class _VCRAsyncClient(object):
cassette = None
def vcr_fetch_impl(cassette, real_fetch_impl):
def __new__(cls, *args, **kwargs):
from vcr.patch import force_reset
with force_reset():
return super(_VCRAsyncClient, cls).__new__(cls, *args, **kwargs)
def initialize(self, *args, **kwargs):
from vcr.patch import force_reset
with force_reset():
self.real_client = self._baseclass(*args, **kwargs)
@property
def io_loop(self):
return self.real_client.io_loop
@property
def _closed(self):
return self.real_client._closed
@property
def defaults(self):
return self.real_client.defaults
def close(self):
from vcr.patch import force_reset
with force_reset():
self.real_client.close()
def fetch_impl(self, request, callback):
@functools.wraps(real_fetch_impl)
def new_fetch_impl(self, request, callback):
headers = dict(request.headers)
if request.user_agent:
headers.setdefault('User-Agent', request.user_agent)
@@ -74,8 +46,8 @@ class _VCRAsyncClient(object):
headers,
)
if self.cassette.can_play_response_for(vcr_request):
vcr_response = self.cassette.play_response(vcr_request)
if cassette.can_play_response_for(vcr_request):
vcr_response = cassette.play_response(vcr_request)
headers = httputil.HTTPHeaders()
recorded_headers = vcr_response['headers']
@@ -93,7 +65,7 @@ class _VCRAsyncClient(object):
)
return callback(response)
else:
if self.cassette.write_protected and self.cassette.filter_request(
if cassette.write_protected and cassette.filter_request(
vcr_request
):
response = HTTPResponse(
@@ -103,8 +75,7 @@ class _VCRAsyncClient(object):
"No match for the request (%r) was found. "
"Can't overwrite existing cassette (%r) in "
"your current record mode (%r)."
% (vcr_request, self.cassette._path,
self.cassette.record_mode)
% (vcr_request, cassette._path, cassette.record_mode)
),
)
return callback(response)
@@ -123,26 +94,9 @@ class _VCRAsyncClient(object):
'headers': headers,
'body': {'string': response.body},
}
self.cassette.append(vcr_request, vcr_response)
cassette.append(vcr_request, vcr_response)
return callback(response)
from vcr.patch import force_reset
with force_reset():
self.real_client.fetch_impl(request, new_callback)
real_fetch_impl(self, request, new_callback)
class VCRAsyncHTTPClient(_VCRAsyncClient, AsyncHTTPClient):
_baseclass = AsyncHTTPClient
class VCRSimpleAsyncHTTPClient(_VCRAsyncClient, SimpleAsyncHTTPClient):
_baseclass = SimpleAsyncHTTPClient
try:
from tornado.curl_httpclient import CurlAsyncHTTPClient
except ImportError: # pragma: no cover
VCRCurlAsyncHTTPClient = None
else:
class VCRCurlAsyncHTTPClient(_VCRAsyncClient, CurlAsyncHTTPClient):
_baseclass = CurlAsyncHTTPClient
return new_fetch_impl