diff --git a/tests/fixtures/wild/domain_redirect.yaml b/tests/fixtures/wild/domain_redirect.yaml index df5d32a..1804b71 100644 --- a/tests/fixtures/wild/domain_redirect.yaml +++ b/tests/fixtures/wild/domain_redirect.yaml @@ -1,10 +1,121 @@ -- request: +- request: !!python/object:vcr.request.Request body: null - headers: !!python/object:requests.structures.CaseInsensitiveDict - _store: - accept: !!python/tuple [Accept, '*/*'] - accept-encoding: !!python/tuple [Accept-Encoding, 'gzip, deflate, compress'] - user-agent: !!python/tuple [User-Agent, vcrpy-test] + headers: !!python/object/apply:__builtin__.frozenset + - - !!python/tuple [Accept-Encoding, 'gzip, deflate, compress'] + - !!python/tuple [User-Agent, vcrpy-test] + - !!python/tuple [Accept, '*/*'] + host: moz.com + method: GET + port: 80 + url: / + response: + body: + string: !!binary | + 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 + headers: {accept-ranges: bytes, age: '1594', cache-control: 'no-cache, must-revalidate, + s-maxage=3600', connection: keep-alive, content-encoding: gzip, content-length: '5300', + content-type: text/html, date: 'Thu, 08 Aug 2013 05:08:16 GMT', expires: 'Fri, + 15 Oct 2004 12:00:00 GMT', server: nginx, server-name: dalmozwww03.dal.moz.com, + vary: Accept-Encoding, via: 1.1 varnish, x-varnish: 1621116313 1621050553} + status: {code: 200, message: OK} +- request: !!python/object:vcr.request.Request + body: null + headers: !!python/object/apply:__builtin__.frozenset + - - !!python/tuple [Accept-Encoding, 'gzip, deflate, compress'] + - !!python/tuple [User-Agent, vcrpy-test] + - !!python/tuple [Accept, '*/*'] host: seomoz.org method: GET port: 80 @@ -13,119 +124,6 @@ body: {string: "\r\n301 Moved Permanently\r\n\r\n

301 Moved Permanently

\r\n
nginx
\r\n\r\n\r\n"} headers: {accept-ranges: bytes, age: '0', connection: keep-alive, content-length: '178', - content-type: text/html, date: 'Tue, 06 Aug 2013 07:01:42 GMT', location: 'http://moz.com/', - server: nginx, server-name: dalmozwww01.dal.moz.com, via: 1.1 varnish, x-varnish: '837899249'} + content-type: text/html, date: 'Thu, 08 Aug 2013 05:08:16 GMT', location: 'http://moz.com/', + server: nginx, server-name: dalmozwww02.dal.moz.com, via: 1.1 varnish, x-varnish: '1621116210'} status: {code: 301, message: Moved Permanently} -- request: - body: null - headers: !!python/object:requests.structures.CaseInsensitiveDict - _store: - accept: !!python/tuple [Accept, '*/*'] - accept-encoding: !!python/tuple [Accept-Encoding, 'gzip, deflate, compress'] - user-agent: !!python/tuple [User-Agent, vcrpy-test] - host: moz.com - method: GET - port: 80 - url: / - response: - body: - string: !!binary | - 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 - headers: {accept-ranges: bytes, age: '2484', cache-control: 'no-cache, must-revalidate, - s-maxage=3600', connection: keep-alive, content-encoding: gzip, content-length: '5300', - content-type: text/html, date: 'Tue, 06 Aug 2013 07:01:42 GMT', expires: 'Fri, - 15 Oct 2004 12:00:00 GMT', server: nginx, server-name: dalmozwww01.dal.moz.com, - vary: Accept-Encoding, via: 1.1 varnish, x-varnish: 837899276 837746321} - status: {code: 200, message: OK} diff --git a/tests/integration/test_urllib2.py b/tests/integration/test_urllib2.py index ac8a6c0..7b93dd6 100644 --- a/tests/integration/test_urllib2.py +++ b/tests/integration/test_urllib2.py @@ -25,14 +25,12 @@ class TestUrllib2Http(TestUrllib2): url = self.scheme + '://httpbin.org/' with vcr.use_cassette(self.fixture('atts.yaml')) as cass: # Ensure that this is empty to begin with - self.assertEqual(len(cass), 0) - self.assertEqual(cass.play_count, 0) - self.assertEqual( - urllib2.urlopen(url).getcode(), - urllib2.urlopen(url).getcode()) + assert len(cass) == 0 + assert cass.play_count == 0 + assert urllib2.urlopen(url).getcode() == urllib2.urlopen(url).getcode() # Ensure that we've now cached a single response - self.assertEqual(len(cass), 1) - self.assertEqual(cass.play_count, 1) + assert len(cass) == 1 + assert cass.play_count == 1 def test_random_body(self): '''Ensure we can read the content, and that it's served from cache''' @@ -41,9 +39,7 @@ class TestUrllib2Http(TestUrllib2): # Ensure that this is empty to begin with self.assertEqual(len(cass), 0) self.assertEqual(cass.play_count, 0) - self.assertEqual( - urllib2.urlopen(url).read(), - urllib2.urlopen(url).read()) + assert urllib2.urlopen(url).read() == urllib2.urlopen(url).read() # Ensure that we've now cached a single response self.assertEqual(len(cass), 1) self.assertEqual(cass.play_count, 1) @@ -85,14 +81,14 @@ class TestUrllib2Http(TestUrllib2): url = self.scheme + '://httpbin.org/get?' + data with vcr.use_cassette(self.fixture('get_data.yaml')) as cass: # Ensure that this is empty to begin with - self.assertEqual(len(cass), 0) - self.assertEqual(cass.play_count, 0) - self.assertEqual( - urllib2.urlopen(url).read(), - urllib2.urlopen(url).read()) + assert len(cass) == 0 + assert cass.play_count == 0 + res1 = urllib2.urlopen(url).read() + res2 = urllib2.urlopen(url).read() + assert res1 == res2 # Ensure that we've now cached a single response - self.assertEqual(len(cass), 1) - self.assertEqual(cass.play_count, 1) + assert len(cass) == 1 + assert cass.play_count == 1 def test_post_data(self): '''Ensure that it works when posting data''' diff --git a/vcr/cassette.py b/vcr/cassette.py index 6eefbc3..0daaa50 100644 --- a/vcr/cassette.py +++ b/vcr/cassette.py @@ -6,6 +6,7 @@ import tempfile # Internal imports from .patch import install, reset from .files import load_cassette, save_cassette +from .request import Request class Cassette(object): @@ -20,8 +21,7 @@ class Cassette(object): def __init__(self, path, data=None): self._path = path - self._requests = [] - self._responses = [] + self.requests = {} self.play_count = 0 if data: self.deserialize(data) @@ -35,12 +35,12 @@ class Cassette(object): return ([{ 'request': req, 'response': res, - } for req, res in zip(self._requests, self._responses)]) + } for req, res in self.requests.iteritems()]) def deserialize(self, source): '''Given a serialized version, load the requests''' - self._requests, self._responses = ( - [r['request'] for r in source], [r['response'] for r in source]) + for r in source: + self.requests[r['request']] = r['response'] def mark_played(self, request=None): ''' @@ -50,27 +50,19 @@ class Cassette(object): def append(self, request, response): '''Add a pair of request, response to this cassette''' - self._requests.append(request) - self._responses.append(response) + self.requests[request] = response def __len__(self): '''Return the number of request / response pairs stored in here''' - return len(self._requests) + return len(self.requests) def __contains__(self, request): '''Return whether or not a request has been stored''' - try: - self._requests.index(request) - return True - except ValueError: - return False + return request in self.requests def response(self, request): '''Find the response corresponding to a request''' - try: - return self._responses[self._requests.index(request)] - except ValueError: - raise KeyError + return self.requests[request] def __enter__(self): '''Patch the fetching libraries we know about''' diff --git a/vcr/request.py b/vcr/request.py new file mode 100644 index 0000000..632c8b2 --- /dev/null +++ b/vcr/request.py @@ -0,0 +1,18 @@ +class Request(object): + + def __init__(self, host, port, method, url, body, headers): + self.host = host + self.port = port + self.method = method + self.url = url + self.body = body + self.headers = frozenset(headers.items()) + + def __key(self): + return (self.host, self.port, self.method, self.url, self.body, self.headers) + + def __hash__(self): + return hash(self.__key()) + + def __eq__(self, other): + return hash(self) == hash(other) diff --git a/vcr/stubs/__init__.py b/vcr/stubs/__init__.py index 693f2e0..2cc09f7 100644 --- a/vcr/stubs/__init__.py +++ b/vcr/stubs/__init__.py @@ -3,6 +3,8 @@ from httplib import HTTPConnection, HTTPSConnection, HTTPMessage from cStringIO import StringIO +from vcr.request import Request + class VCRHTTPResponse(object): """ @@ -44,14 +46,15 @@ class VCRConnectionMixin: def request(self, method, url, body=None, headers=None): '''Persist the request metadata in self._vcr''' - self._request = { - 'host': self.host, - 'port': self.port, - 'method': method, - 'url': url, - 'body': body, - 'headers': headers or {}, - } + self._request = Request( + host = self.host, + port = self.port, + method = method, + url = url, + body = body, + headers = headers or {} + ) + # Check if we have a cassette set, and if we have a response saved. # If so, there's no need to keep processing and we can bail if self.cassette and self._request in self.cassette: