diff --git a/.travis.yml b/.travis.yml index 380e22d1..9acbdff9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: python before_install: openssl version env: - - WITH_REQUESTS="True" + - WITH_REQUESTS="2.x" + - WITH_REQUESTS="1.x" - WITH_REQUESTS="False" python: - 2.6 @@ -9,5 +10,6 @@ python: - pypy install: - pip install PyYAML pytest --use-mirrors - - if [ $WITH_REQUESTS = "True" ] ; then pip install requests; fi + - if [ $WITH_REQUESTS = "1.x" ] ; then pip install requests==1.2.3; fi + - if [ $WITH_REQUESTS = "2.x" ] ; then pip install requests; fi script: python setup.py test diff --git a/README.md b/README.md index f320486c..a53cfb39 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,7 @@ This library is a work in progress, so the API might change on you. There are probably some [bugs](https://github.com/kevin1024/vcrpy/issues?labels=bug&page=1&state=open) floating around too. ##Changelog +* 0.3.5: Fix compatibility with requests 2.x * 0.3.4: Bugfix: close file before renaming it. This fixes an issue on Windows. Thanks @smallcode for the fix. * 0.3.3: Bugfix for error message when an unreigstered custom matcher was used diff --git a/setup.py b/setup.py index d259f947..111f6a4f 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ def run_tests(self): sys.exit(errno) setup(name='vcrpy', - version='0.3.4', + version='0.3.5', description="A Python port of Ruby's VCR to make mocking HTTP easier", author='Kevin McCarthy', author_email='me@kevinmccarthy.org', diff --git a/tox.ini b/tox.ini index a8cd4240..884cf464 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, pypy, py26requests, py27requests, pypyrequests +envlist = py26, py27, pypy, py26requests, py27requests, pypyrequests, py26oldrequests, py27oldrequests, pypyoldrequests [testenv] commands = @@ -13,6 +13,27 @@ deps = pytest PyYAML +[testenv:py26oldrequests] +basepython = python2.6 +deps = + pytest + PyYAML + requests==1.2.3 + +[testenv:py27oldrequests] +basepython = python2.7 +deps = + pytest + PyYAML + requests==1.2.3 + +[testenv:pypyoldrequests] +basepython = pypy +deps = + pytest + PyYAML + requests==1.2.3 + [testenv:py26requests] basepython = python2.6 deps = diff --git a/vcr/patch.py b/vcr/patch.py index 7f0b8b33..e77e7592 100644 --- a/vcr/patch.py +++ b/vcr/patch.py @@ -36,7 +36,7 @@ def install(cassette): httplib.HTTPConnection.cassette = cassette httplib.HTTPSConnection.cassette = cassette - # patch requests + # patch requests v1.x try: import requests.packages.urllib3.connectionpool as cpool from .stubs.requests_stubs import VCRVerifiedHTTPSConnection @@ -44,6 +44,11 @@ def install(cassette): cpool.VerifiedHTTPSConnection.cassette = cassette cpool.HTTPConnection = VCRHTTPConnection cpool.HTTPConnection.cassette = cassette + # patch requests v2.x + cpool.HTTPConnectionPool.ConnectionCls = VCRHTTPConnection + cpool.HTTPConnectionPool.cassette = cassette + cpool.HTTPSConnectionPool.ConnectionCls = VCRHTTPSConnection + cpool.HTTPSConnectionPool.cassette = cassette except ImportError: # pragma: no cover pass @@ -68,6 +73,8 @@ def reset(): import requests.packages.urllib3.connectionpool as cpool cpool.VerifiedHTTPSConnection = _VerifiedHTTPSConnection cpool.HTTPConnection = _HTTPConnection + cpool.HTTPConnectionPool.ConnectionCls = _HTTPConnection + cpool.HTTPSConnectionPool.ConnectionCls = _HTTPSConnection except ImportError: # pragma: no cover pass @@ -75,5 +82,7 @@ def reset(): import urllib3.connectionpool as cpool cpool.VerifiedHTTPSConnection = _VerifiedHTTPSConnection cpool.HTTPConnection = _HTTPConnection + cpool.HTTPConnectionPool.ConnectionCls = _HTTPConnection + cpool.HTTPSConnectionPool.ConnectionCls = _HTTPSConnection except ImportError: # pragma: no cover pass diff --git a/vcr/stubs/__init__.py b/vcr/stubs/__init__.py index d779cc26..0e50d08c 100644 --- a/vcr/stubs/__init__.py +++ b/vcr/stubs/__init__.py @@ -77,6 +77,22 @@ def send(self, data): ''' self._vcr_request.body = (self._vcr_request.body or '') + data + def close(self): + self._restore_socket() + self._baseclass.close(self) + + def _restore_socket(self): + """ + Since some libraries (REQUESTS!!) decide to set options on + connection.socket, I need to delete the socket attribute + (which makes requests think this is a AppEngine connection) + and then restore it when I want to make the actual request. + This function restores it to its standard initial value + (which is None) + """ + if not hasattr(self, 'sock'): + self.sock = None + def _send_request(self, method, url, body, headers): """ Copy+pasted from python stdlib 2.6 source because it @@ -132,6 +148,7 @@ def _send_output(self, message_body=None): if isinstance(message_body, str): msg += message_body message_body = None + self._restore_socket() self._baseclass.send(self, msg) if message_body is not None: #message_body was not a string (i.e. it is a file) and @@ -156,7 +173,10 @@ def getresponse(self, _=False): # Otherwise, we should send the request, then get the response # and return it. - # make the request + # restore sock's value to None, since we need a real socket + self._restore_socket() + + #make the actual request self._baseclass.request( self, method=self._vcr_request.method, @@ -189,6 +209,8 @@ class VCRHTTPConnection(VCRConnectionMixin, HTTPConnection): def __init__(self, *args, **kwargs): HTTPConnection.__init__(self, *args, **kwargs) + # see VCRConnectionMixin._restore_socket for the motivation here + del self.sock class VCRHTTPSConnection(VCRConnectionMixin, HTTPSConnection): @@ -203,3 +225,5 @@ class because HTTPConnection when this happens has been replaced by HTTPConnection.__init__(self, *args, **kwargs) self.key_file = kwargs.pop('key_file', None) self.cert_file = kwargs.pop('cert_file', None) + # see VCRConnectionMixin._restore_socket for the motivation here + del self.sock