mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-11 18:06:10 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d33b19b5bb | ||
|
|
2275749eaa | ||
|
|
16fbe40d87 | ||
|
|
deed8cab97 | ||
|
|
cf8646d8d6 | ||
|
|
c03459e582 |
@@ -1,7 +1,8 @@
|
|||||||
language: python
|
language: python
|
||||||
before_install: openssl version
|
before_install: openssl version
|
||||||
env:
|
env:
|
||||||
- WITH_REQUESTS="True"
|
- WITH_REQUESTS="2.x"
|
||||||
|
- WITH_REQUESTS="1.x"
|
||||||
- WITH_REQUESTS="False"
|
- WITH_REQUESTS="False"
|
||||||
python:
|
python:
|
||||||
- 2.6
|
- 2.6
|
||||||
@@ -9,5 +10,6 @@ python:
|
|||||||
- pypy
|
- pypy
|
||||||
install:
|
install:
|
||||||
- pip install PyYAML pytest --use-mirrors
|
- 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
|
script: python setup.py test
|
||||||
|
|||||||
@@ -259,6 +259,12 @@ 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.
|
There are probably some [bugs](https://github.com/kevin1024/vcrpy/issues?labels=bug&page=1&state=open) floating around too.
|
||||||
|
|
||||||
##Changelog
|
##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
|
||||||
|
* 0.3.2: Fix issue with new config syntax and the `match_on` parameter.
|
||||||
|
Thanks, @chromy!
|
||||||
* 0.3.1: Fix issue causing full paths to be sent on the HTTP request
|
* 0.3.1: Fix issue causing full paths to be sent on the HTTP request
|
||||||
line.
|
line.
|
||||||
* 0.3.0: *Backwards incompatible release* - Added support for record
|
* 0.3.0: *Backwards incompatible release* - Added support for record
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -19,7 +19,7 @@ class PyTest(TestCommand):
|
|||||||
sys.exit(errno)
|
sys.exit(errno)
|
||||||
|
|
||||||
setup(name='vcrpy',
|
setup(name='vcrpy',
|
||||||
version='0.3.1',
|
version='0.3.5',
|
||||||
description="A Python port of Ruby's VCR to make mocking HTTP easier",
|
description="A Python port of Ruby's VCR to make mocking HTTP easier",
|
||||||
author='Kevin McCarthy',
|
author='Kevin McCarthy',
|
||||||
author_email='me@kevinmccarthy.org',
|
author_email='me@kevinmccarthy.org',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import urllib2
|
import urllib2
|
||||||
|
import pytest
|
||||||
import vcr
|
import vcr
|
||||||
|
|
||||||
|
|
||||||
@@ -34,3 +35,22 @@ def test_override_set_cassette_library_dir(tmpdir):
|
|||||||
|
|
||||||
assert os.path.exists(str(tmpdir.join('subdir2').join('test.json')))
|
assert os.path.exists(str(tmpdir.join('subdir2').join('test.json')))
|
||||||
assert not os.path.exists(str(tmpdir.join('subdir').join('test.json')))
|
assert not os.path.exists(str(tmpdir.join('subdir').join('test.json')))
|
||||||
|
|
||||||
|
|
||||||
|
def test_override_match_on(tmpdir):
|
||||||
|
my_vcr = vcr.VCR(match_on=['method'])
|
||||||
|
|
||||||
|
with my_vcr.use_cassette(str(tmpdir.join('test.json'))) as cass:
|
||||||
|
urllib2.urlopen('http://httpbin.org/')
|
||||||
|
urllib2.urlopen('http://httpbin.org/get')
|
||||||
|
|
||||||
|
assert len(cass) == 1
|
||||||
|
assert cass.play_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_matcher():
|
||||||
|
my_vcr = vcr.VCR()
|
||||||
|
my_vcr.register_matcher("awesome", object)
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
with my_vcr.use_cassette("test.yaml", match_on=['notawesome']):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ def test_flickr_multipart_upload():
|
|||||||
_pretend_to_be_flickr_library()
|
_pretend_to_be_flickr_library()
|
||||||
assert cass.play_count == 1
|
assert cass.play_count == 1
|
||||||
|
|
||||||
|
|
||||||
def test_flickr_should_respond_with_200(tmpdir):
|
def test_flickr_should_respond_with_200(tmpdir):
|
||||||
testfile = str(tmpdir.join('flickr.yml'))
|
testfile = str(tmpdir.join('flickr.yml'))
|
||||||
with vcr.use_cassette(testfile):
|
with vcr.use_cassette(testfile):
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ def test_cassette_len():
|
|||||||
def _mock_requests_match(request1, request2, matchers):
|
def _mock_requests_match(request1, request2, matchers):
|
||||||
return request1 == request2
|
return request1 == request2
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('vcr.cassette.requests_match', _mock_requests_match)
|
@mock.patch('vcr.cassette.requests_match', _mock_requests_match)
|
||||||
def test_cassette_contains():
|
def test_cassette_contains():
|
||||||
a = Cassette('test')
|
a = Cassette('test')
|
||||||
|
|||||||
23
tox.ini
23
tox.ini
@@ -4,7 +4,7 @@
|
|||||||
# and then run "tox" from this directory.
|
# and then run "tox" from this directory.
|
||||||
|
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py26, py27, pypy, py26requests, py27requests, pypyrequests
|
envlist = py26, py27, pypy, py26requests, py27requests, pypyrequests, py26oldrequests, py27oldrequests, pypyoldrequests
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands =
|
commands =
|
||||||
@@ -13,6 +13,27 @@ deps =
|
|||||||
pytest
|
pytest
|
||||||
PyYAML
|
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]
|
[testenv:py26requests]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps =
|
deps =
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ class VCR(object):
|
|||||||
def __init__(self,
|
def __init__(self,
|
||||||
serializer='yaml',
|
serializer='yaml',
|
||||||
cassette_library_dir=None,
|
cassette_library_dir=None,
|
||||||
record_mode="once"):
|
record_mode="once",
|
||||||
|
match_on=['url', 'method'],
|
||||||
|
):
|
||||||
self.serializer = serializer
|
self.serializer = serializer
|
||||||
self.match_on = ['url', 'method']
|
self.match_on = match_on
|
||||||
self.cassette_library_dir = cassette_library_dir
|
self.cassette_library_dir = cassette_library_dir
|
||||||
self.serializers = {
|
self.serializers = {
|
||||||
'yaml': yamlserializer,
|
'yaml': yamlserializer,
|
||||||
@@ -40,10 +42,9 @@ class VCR(object):
|
|||||||
try:
|
try:
|
||||||
matchers = [self.matchers[m] for m in matcher_names]
|
matchers = [self.matchers[m] for m in matcher_names]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print "Matcher {0} doesn't exist or isn't registered".format(
|
raise KeyError(
|
||||||
matcher_name
|
"Matcher {0} doesn't exist or isn't registered".format(m)
|
||||||
)
|
)
|
||||||
raise KeyError
|
|
||||||
return matchers
|
return matchers
|
||||||
|
|
||||||
def use_cassette(self, path, **kwargs):
|
def use_cassette(self, path, **kwargs):
|
||||||
|
|||||||
11
vcr/patch.py
11
vcr/patch.py
@@ -36,7 +36,7 @@ def install(cassette):
|
|||||||
httplib.HTTPConnection.cassette = cassette
|
httplib.HTTPConnection.cassette = cassette
|
||||||
httplib.HTTPSConnection.cassette = cassette
|
httplib.HTTPSConnection.cassette = cassette
|
||||||
|
|
||||||
# patch requests
|
# patch requests v1.x
|
||||||
try:
|
try:
|
||||||
import requests.packages.urllib3.connectionpool as cpool
|
import requests.packages.urllib3.connectionpool as cpool
|
||||||
from .stubs.requests_stubs import VCRVerifiedHTTPSConnection
|
from .stubs.requests_stubs import VCRVerifiedHTTPSConnection
|
||||||
@@ -44,6 +44,11 @@ def install(cassette):
|
|||||||
cpool.VerifiedHTTPSConnection.cassette = cassette
|
cpool.VerifiedHTTPSConnection.cassette = cassette
|
||||||
cpool.HTTPConnection = VCRHTTPConnection
|
cpool.HTTPConnection = VCRHTTPConnection
|
||||||
cpool.HTTPConnection.cassette = cassette
|
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
|
except ImportError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -68,6 +73,8 @@ def reset():
|
|||||||
import requests.packages.urllib3.connectionpool as cpool
|
import requests.packages.urllib3.connectionpool as cpool
|
||||||
cpool.VerifiedHTTPSConnection = _VerifiedHTTPSConnection
|
cpool.VerifiedHTTPSConnection = _VerifiedHTTPSConnection
|
||||||
cpool.HTTPConnection = _HTTPConnection
|
cpool.HTTPConnection = _HTTPConnection
|
||||||
|
cpool.HTTPConnectionPool.ConnectionCls = _HTTPConnection
|
||||||
|
cpool.HTTPSConnectionPool.ConnectionCls = _HTTPSConnection
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -75,5 +82,7 @@ def reset():
|
|||||||
import urllib3.connectionpool as cpool
|
import urllib3.connectionpool as cpool
|
||||||
cpool.VerifiedHTTPSConnection = _VerifiedHTTPSConnection
|
cpool.VerifiedHTTPSConnection = _VerifiedHTTPSConnection
|
||||||
cpool.HTTPConnection = _HTTPConnection
|
cpool.HTTPConnection = _HTTPConnection
|
||||||
|
cpool.HTTPConnectionPool.ConnectionCls = _HTTPConnection
|
||||||
|
cpool.HTTPSConnectionPool.ConnectionCls = _HTTPSConnection
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -77,6 +77,22 @@ class VCRConnectionMixin:
|
|||||||
'''
|
'''
|
||||||
self._vcr_request.body = (self._vcr_request.body or '') + 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):
|
def _send_request(self, method, url, body, headers):
|
||||||
"""
|
"""
|
||||||
Copy+pasted from python stdlib 2.6 source because it
|
Copy+pasted from python stdlib 2.6 source because it
|
||||||
@@ -132,6 +148,7 @@ class VCRConnectionMixin:
|
|||||||
if isinstance(message_body, str):
|
if isinstance(message_body, str):
|
||||||
msg += message_body
|
msg += message_body
|
||||||
message_body = None
|
message_body = None
|
||||||
|
self._restore_socket()
|
||||||
self._baseclass.send(self, msg)
|
self._baseclass.send(self, msg)
|
||||||
if message_body is not None:
|
if message_body is not None:
|
||||||
#message_body was not a string (i.e. it is a file) and
|
#message_body was not a string (i.e. it is a file) and
|
||||||
@@ -156,7 +173,10 @@ class VCRConnectionMixin:
|
|||||||
# Otherwise, we should send the request, then get the response
|
# Otherwise, we should send the request, then get the response
|
||||||
# and return it.
|
# 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._baseclass.request(
|
||||||
self,
|
self,
|
||||||
method=self._vcr_request.method,
|
method=self._vcr_request.method,
|
||||||
@@ -189,6 +209,8 @@ class VCRHTTPConnection(VCRConnectionMixin, HTTPConnection):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
HTTPConnection.__init__(self, *args, **kwargs)
|
HTTPConnection.__init__(self, *args, **kwargs)
|
||||||
|
# see VCRConnectionMixin._restore_socket for the motivation here
|
||||||
|
del self.sock
|
||||||
|
|
||||||
|
|
||||||
class VCRHTTPSConnection(VCRConnectionMixin, HTTPSConnection):
|
class VCRHTTPSConnection(VCRConnectionMixin, HTTPSConnection):
|
||||||
@@ -203,3 +225,5 @@ class VCRHTTPSConnection(VCRConnectionMixin, HTTPSConnection):
|
|||||||
HTTPConnection.__init__(self, *args, **kwargs)
|
HTTPConnection.__init__(self, *args, **kwargs)
|
||||||
self.key_file = kwargs.pop('key_file', None)
|
self.key_file = kwargs.pop('key_file', None)
|
||||||
self.cert_file = kwargs.pop('cert_file', None)
|
self.cert_file = kwargs.pop('cert_file', None)
|
||||||
|
# see VCRConnectionMixin._restore_socket for the motivation here
|
||||||
|
del self.sock
|
||||||
|
|||||||
Reference in New Issue
Block a user