1
0
mirror of https://github.com/kevin1024/vcrpy.git synced 2025-12-09 09:13: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') yield get(get_client(), 'http://httpbin.org/status/404')
except http.HTTPError as e: except http.HTTPError as e:
assert e.code == 404 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 to save the original types for Tornado
try: try:
import tornado.httpclient
import tornado.simple_httpclient import tornado.simple_httpclient
except ImportError: # pragma: no cover except ImportError: # pragma: no cover
pass pass
else: else:
_AsyncHTTPClient = tornado.httpclient.AsyncHTTPClient _SimpleAsyncHTTPClient_fetch_impl = \
_SimpleAsyncHTTPClient = tornado.simple_httpclient.SimpleAsyncHTTPClient tornado.simple_httpclient.SimpleAsyncHTTPClient.fetch_impl
try: try:
@@ -68,7 +67,8 @@ try:
except ImportError: # pragma: no cover except ImportError: # pragma: no cover
pass pass
else: else:
_CurlAsyncHTTPClient = tornado.curl_httpclient.CurlAsyncHTTPClient _CurlAsyncHTTPClient_fetch_impl = \
tornado.curl_httpclient.CurlAsyncHTTPClient.fetch_impl
class CassettePatcherBuilder(object): class CassettePatcherBuilder(object):
@@ -228,23 +228,27 @@ class CassettePatcherBuilder(object):
@_build_patchers_from_mock_triples_decorator @_build_patchers_from_mock_triples_decorator
def _tornado(self): def _tornado(self):
try: try:
import tornado.httpclient as http
import tornado.simple_httpclient as simple import tornado.simple_httpclient as simple
except ImportError: # pragma: no cover except ImportError: # pragma: no cover
pass pass
else: else:
from .stubs.tornado_stubs import VCRAsyncHTTPClient from .stubs.tornado_stubs import vcr_fetch_impl
from .stubs.tornado_stubs import VCRSimpleAsyncHTTPClient
yield http, 'AsyncHTTPClient', VCRAsyncHTTPClient new_fetch_impl = vcr_fetch_impl(
yield simple, 'SimpleAsyncHTTPClient', VCRSimpleAsyncHTTPClient self._cassette, _SimpleAsyncHTTPClient_fetch_impl
)
yield simple.SimpleAsyncHTTPClient, 'fetch_impl', new_fetch_impl
try: try:
import tornado.curl_httpclient as curl import tornado.curl_httpclient as curl
except ImportError: # pragma: no cover except ImportError: # pragma: no cover
pass pass
else: else:
from .stubs.tornado_stubs import VCRCurlAsyncHTTPClient from .stubs.tornado_stubs import vcr_fetch_impl
yield curl, 'CurlAsyncHTTPClient', VCRCurlAsyncHTTPClient
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): def _urllib3_patchers(self, cpool, stubs):
http_connection_remover = ConnectionRemover( http_connection_remover = ConnectionRemover(
@@ -362,19 +366,25 @@ def reset_patchers():
_CertValidatingHTTPSConnection) _CertValidatingHTTPSConnection)
try: try:
import tornado.httpclient as http
import tornado.simple_httpclient as simple import tornado.simple_httpclient as simple
except ImportError: # pragma: no cover except ImportError: # pragma: no cover
pass pass
else: else:
yield mock.patch.object(http, 'AsyncHTTPClient', _AsyncHTTPClient) yield mock.patch.object(
yield mock.patch.object(simple, 'SimpleAsyncHTTPClient', _SimpleAsyncHTTPClient) simple.SimpleAsyncHTTPClient,
'fetch_impl',
_SimpleAsyncHTTPClient_fetch_impl,
)
try: try:
import tornado.curl_httpclient as curl import tornado.curl_httpclient as curl
except ImportError: # pragma: no cover except ImportError: # pragma: no cover
pass pass
else: else:
yield mock.patch.object(curl, 'CurlAsyncHTTPClient', _CurlAsyncHTTPClient) yield mock.patch.object(
curl.CurlAsyncHTTPClient,
'fetch_impl',
_CurlAsyncHTTPClient_fetch_impl,
)
@contextlib.contextmanager @contextlib.contextmanager

View File

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