mirror of
https://github.com/kevin1024/vcrpy.git
synced 2025-12-08 16:53:23 +00:00
Cassettes now store multiple requests
This commit is contained in:
@@ -42,8 +42,8 @@ Ruby's VCR are not compatible with VCR.py. The API is similar but VCR.py
|
||||
doesn't have nearly as many features.
|
||||
|
||||
##Known Issues
|
||||
* Only works with the first HTTP request made in each use_cassette block. That's because I haven't gotten around to implementing multiple requests yet. This means anything that does a 301 / 302 won't work.
|
||||
* Probably only works with urllib2. Hey, doesn't [requests](http://docs.python-requests.org/en/latest/index.html) use urllib2? Maybe that works too then.
|
||||
* Loading urls that do a 301/302 redirect don't work
|
||||
|
||||
##Similar libraries in Python
|
||||
Neither of these really implement the API I want, but I have cribbed some code
|
||||
|
||||
17
test.py
17
test.py
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import unittest
|
||||
import vcr
|
||||
from vcr.cassette import Cassette
|
||||
import urllib2
|
||||
|
||||
TEST_CASSETTE_FILE = 'test/test_req.yaml'
|
||||
@@ -48,7 +49,7 @@ class TestHttps(unittest.TestCase):
|
||||
os.remove(TEST_CASSETTE_FILE)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def test_response_code(self):
|
||||
code = urllib2.urlopen('https://api.twitter.com/1/legal/tos.json').getcode()
|
||||
with vcr.use_cassette(TEST_CASSETTE_FILE):
|
||||
@@ -65,7 +66,19 @@ class TestHttps(unittest.TestCase):
|
||||
with vcr.use_cassette(TEST_CASSETTE_FILE):
|
||||
headers = urllib2.urlopen('https://api.twitter.com/1/legal/tos.json').info().items()
|
||||
self.assertEqual(headers, urllib2.urlopen('https://api.twitter.com/1/legal/tos.json').info().items())
|
||||
|
||||
|
||||
class TestCassette(unittest.TestCase):
|
||||
def test_serialize_cassette(self):
|
||||
c1 = Cassette()
|
||||
c1.requests = ['a','b','c']
|
||||
c1.responses = ['d','e','f']
|
||||
ser = c1.serialize()
|
||||
c2 = Cassette(ser)
|
||||
self.assertEqual(c1.requests,c2.requests)
|
||||
self.assertEqual(c1.responses,c2.responses)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
import yaml
|
||||
|
||||
|
||||
class Cassette(object):
|
||||
def __init__(self):
|
||||
def __init__(self, ser_cassette=None):
|
||||
self.requests = []
|
||||
self.responses = []
|
||||
if ser_cassette:
|
||||
self._unserialize(ser_cassette)
|
||||
|
||||
def serialize(self):
|
||||
return yaml.dump([{
|
||||
return ([{
|
||||
'request': req,
|
||||
'response': res,
|
||||
} for req,res in zip(self.requests,self.responses)])
|
||||
} for req, res in zip(self.requests, self.responses)])
|
||||
|
||||
def _unserialize(self, source):
|
||||
self.requests, self.responses = [r['request'] for r in source], [r['response'] for r in source]
|
||||
|
||||
def get_request(self, match):
|
||||
try:
|
||||
return self.requests[self.requests.index(match)]
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def get_response(self, match):
|
||||
try:
|
||||
return self.responses[self.requests.index(match)]
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import os
|
||||
import yaml
|
||||
from .cassette import Cassette
|
||||
|
||||
|
||||
def load_cassette(cassette_path):
|
||||
try:
|
||||
return yaml.load(open(cassette_path))
|
||||
pc = yaml.load(open(cassette_path))
|
||||
cassette = Cassette(pc)
|
||||
return cassette
|
||||
except IOError:
|
||||
return None
|
||||
|
||||
@@ -14,4 +17,4 @@ def save_cassette(cassette_path, cassette):
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
with open(cassette_path, 'wc') as cassette_file:
|
||||
cassette_file.write(cassette.serialize())
|
||||
cassette_file.write(yaml.dump(cassette.serialize()))
|
||||
|
||||
@@ -12,14 +12,15 @@ def install(cassette_path):
|
||||
httplib.HTTPConnection._vcr_cassette_path = cassette_path
|
||||
httplib.HTTPSConnection._vcr_cassette_path = cassette_path
|
||||
|
||||
|
||||
def reset():
|
||||
httplib.HTTPConnection = httplib.HTTP._connection_class = _HTTPConnection
|
||||
httplib.HTTPSConnection = httplib.HTTPS._connection_class = \
|
||||
_HTTPSConnection
|
||||
|
||||
|
||||
@contextmanager
|
||||
def use_cassette(cassette_path):
|
||||
install(cassette_path)
|
||||
yield
|
||||
reset()
|
||||
|
||||
|
||||
24
vcr/stubs.py
24
vcr/stubs.py
@@ -28,9 +28,23 @@ class VCRHTTPConnection(HTTPConnection):
|
||||
def _save_cassette(self):
|
||||
save_cassette(self._vcr_cassette_path, self._cassette)
|
||||
|
||||
def request(self, method, url, body=None, headers={}):
|
||||
def _load_old_response(self):
|
||||
old_cassette = load_cassette(self._vcr_cassette_path)
|
||||
if old_cassette:
|
||||
return old_cassette.get_response(self._vcr)
|
||||
|
||||
def request(self, method, url, body=None, headers={}):
|
||||
"""
|
||||
Persist the request metadata in self._vcr
|
||||
"""
|
||||
self._vcr = {
|
||||
'method': method,
|
||||
'url': url,
|
||||
'body': body,
|
||||
'headers': headers,
|
||||
}
|
||||
old_cassette = load_cassette(self._vcr_cassette_path)
|
||||
if old_cassette and old_cassette.get_request(self._vcr):
|
||||
return
|
||||
self._cassette.requests.append(dict(
|
||||
method=method,
|
||||
@@ -41,8 +55,8 @@ class VCRHTTPConnection(HTTPConnection):
|
||||
return HTTPConnection.request(self, method, url, body=body, headers=headers)
|
||||
|
||||
def getresponse(self, buffering=False):
|
||||
old_cassette = load_cassette(self._vcr_cassette_path)
|
||||
if not old_cassette:
|
||||
old_response = self._load_old_response()
|
||||
if not old_response:
|
||||
response = HTTPConnection.getresponse(self)
|
||||
self._cassette.responses.append({
|
||||
'status': {'code': response.status, 'message': response.reason},
|
||||
@@ -50,8 +64,8 @@ class VCRHTTPConnection(HTTPConnection):
|
||||
'body': {'string': response.read()},
|
||||
})
|
||||
self._save_cassette()
|
||||
old_cassette = load_cassette(self._vcr_cassette_path)
|
||||
return VCRHTTPResponse(old_cassette[0]['response'])
|
||||
old_response = self._load_old_response()
|
||||
return VCRHTTPResponse(old_response)
|
||||
|
||||
|
||||
class VCRHTTPSConnection(VCRHTTPConnection):
|
||||
|
||||
Reference in New Issue
Block a user