diff --git a/.travis.yml b/.travis.yml index a3f5e73..9dc2e6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ env: - secure: AifoKzwhjV94cmcQZrdQmqRu/9rkZZvWpwBv1daeAQpLOKFPGsOm3D+x2cSw9+iCfkgDZDfqQVv1kCaFVxTll8v8jTq5SJdqEY0NmGWbj/UkNtShh609oRDsuzLxAEwtVKYjf/h8K2BRea+bl1tGkwZ2vtmYS6dxNlAijjWOfds= - secure: LBSEg/gMj4u4Hrpo3zs6Y/1mTpd2RtcN49mZIFgTdbJ9IhpiNPqcEt647Lz94F9Eses2x2WbNuKqZKZZReY7QLbEzU1m0nN5jlaKrjcG5NR5clNABfFFyhgc0jBikyS4abAG8jc2efeaTrFuQwdoF4sE8YiVrkiVj2X5Xoi6sBk= matrix: + - TOX_SUFFIX="flakes" - TOX_SUFFIX="requests22" - TOX_SUFFIX="requests23" - TOX_SUFFIX="requests24" @@ -37,7 +38,7 @@ python: - pypy install: - pip install tox -- python setup.py install +- if [[ $TOX_SUFFIX != flakes ]]; then python setup.py install ; fi script: - v=$TRAVIS_PYTHON_VERSION - if [[ ${v%py} != $v ]]; then TOXPY=$v; else TOXPY=py"${v/./}"; fi diff --git a/docs/conf.py b/docs/conf.py index 803c722..afb28cc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os -import shlex # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/tests/integration/test_boto.py b/tests/integration/test_boto.py index d00cf27..84132d7 100644 --- a/tests/integration/test_boto.py +++ b/tests/integration/test_boto.py @@ -31,26 +31,26 @@ def test_boto_without_vcr(): def test_boto_medium_difficulty(tmpdir): s3_conn = S3Connection() s3_bucket = s3_conn.get_bucket('boto-demo-1394171994') # a bucket you can access - with vcr.use_cassette(str(tmpdir.join('boto-medium.yml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('boto-medium.yml'))): k = Key(s3_bucket) k.key = 'test.txt' k.set_contents_from_string('hello world i am a string') - with vcr.use_cassette(str(tmpdir.join('boto-medium.yml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('boto-medium.yml'))): k = Key(s3_bucket) k.key = 'test.txt' k.set_contents_from_string('hello world i am a string') def test_boto_hardcore_mode(tmpdir): - with vcr.use_cassette(str(tmpdir.join('boto-hardcore.yml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('boto-hardcore.yml'))): s3_conn = S3Connection() s3_bucket = s3_conn.get_bucket('boto-demo-1394171994') # a bucket you can access k = Key(s3_bucket) k.key = 'test.txt' k.set_contents_from_string('hello world i am a string') - with vcr.use_cassette(str(tmpdir.join('boto-hardcore.yml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('boto-hardcore.yml'))): s3_conn = S3Connection() s3_bucket = s3_conn.get_bucket('boto-demo-1394171994') # a bucket you can access k = Key(s3_bucket) @@ -68,10 +68,10 @@ def test_boto_iam(tmpdir): # Ensure that boto uses CertValidatingHTTPSConnection boto.config.set('Boto', 'https_validate_certificates', 'true') - with vcr.use_cassette(str(tmpdir.join('boto-iam.yml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('boto-iam.yml'))): iam_conn = boto.iam.connect_to_region('universal') iam_conn.get_all_users() - with vcr.use_cassette(str(tmpdir.join('boto-iam.yml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('boto-iam.yml'))): iam_conn = boto.iam.connect_to_region('universal') iam_conn.get_all_users() diff --git a/tests/integration/test_filter.py b/tests/integration/test_filter.py index 45c3f78..43f63ff 100644 --- a/tests/integration/test_filter.py +++ b/tests/integration/test_filter.py @@ -78,9 +78,11 @@ def test_filter_json_post_data(tmpdir): def test_filter_callback(tmpdir): url = 'http://httpbin.org/get' cass_file = str(tmpdir.join('basic_auth_filter.yaml')) + def before_record_cb(request): if request.path != '/get': return request + # Test the legacy keyword. my_vcr = vcr.VCR(before_record=before_record_cb) with my_vcr.use_cassette(cass_file, filter_headers=['authorization']) as cass: diff --git a/tests/integration/test_httplib2.py b/tests/integration/test_httplib2.py index f830a06..eaa5d75 100644 --- a/tests/integration/test_httplib2.py +++ b/tests/integration/test_httplib2.py @@ -24,11 +24,11 @@ def scheme(request): def test_response_code(scheme, tmpdir): '''Ensure we can read a response code from a fetch''' url = scheme + '://httpbin.org/' - with vcr.use_cassette(str(tmpdir.join('atts.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('atts.yaml'))): resp, _ = httplib2.Http().request(url) code = resp.status - with vcr.use_cassette(str(tmpdir.join('atts.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('atts.yaml'))): resp, _ = httplib2.Http().request(url) assert code == resp.status @@ -36,11 +36,11 @@ def test_response_code(scheme, tmpdir): def test_random_body(scheme, tmpdir): '''Ensure we can read the content, and that it's served from cache''' url = scheme + '://httpbin.org/bytes/1024' - with vcr.use_cassette(str(tmpdir.join('body.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('body.yaml'))): _, content = httplib2.Http().request(url) body = content - with vcr.use_cassette(str(tmpdir.join('body.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('body.yaml'))): _, content = httplib2.Http().request(url) assert body == content @@ -48,26 +48,28 @@ def test_random_body(scheme, tmpdir): def test_response_headers(scheme, tmpdir): '''Ensure we can get information from the response''' url = scheme + '://httpbin.org/' - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): resp, _ = httplib2.Http().request(url) headers = resp.items() - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): resp, _ = httplib2.Http().request(url) assert set(headers) == set(resp.items()) + def test_effective_url(scheme, tmpdir): '''Ensure that the effective_url is captured''' url = scheme + '://httpbin.org/redirect-to?url=/html' - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): resp, _ = httplib2.Http().request(url) effective_url = resp['content-location'] assert effective_url == scheme + '://httpbin.org/html' - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): resp, _ = httplib2.Http().request(url) assert effective_url == resp['content-location'] + def test_multiple_requests(scheme, tmpdir): '''Ensure that we can cache multiple requests''' urls = [ @@ -85,10 +87,10 @@ def test_get_data(scheme, tmpdir): '''Ensure that it works with query data''' data = urlencode({'some': 1, 'data': 'here'}) url = scheme + '://httpbin.org/get?' + data - with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))): _, res1 = httplib2.Http().request(url) - with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))): _, res2 = httplib2.Http().request(url) assert res1 == res2 @@ -98,7 +100,7 @@ def test_post_data(scheme, tmpdir): '''Ensure that it works when posting data''' data = urlencode({'some': 1, 'data': 'here'}) url = scheme + '://httpbin.org/post' - with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))): _, res1 = httplib2.Http().request(url, "POST", data) with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: @@ -112,7 +114,7 @@ def test_post_unicode_data(scheme, tmpdir): '''Ensure that it works when posting unicode data''' data = urlencode({'snowman': u'☃'.encode('utf-8')}) url = scheme + '://httpbin.org/post' - with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))): _, res1 = httplib2.Http().request(url, "POST", data) with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: diff --git a/tests/integration/test_ignore.py b/tests/integration/test_ignore.py index 9d0b0ae..d32682f 100644 --- a/tests/integration/test_ignore.py +++ b/tests/integration/test_ignore.py @@ -1,7 +1,5 @@ -import base64 -import pytest -from six.moves.urllib.request import urlopen, Request -from six.moves.urllib.error import HTTPError +from six.moves.urllib.request import urlopen + import vcr @@ -40,6 +38,7 @@ def test_ignore_localhost_and_httpbin(tmpdir, httpserver): urlopen(httpserver.url) assert len(cass) == 0 + def test_ignore_localhost_twice(tmpdir, httpserver): httpserver.serve_content('Hello!') cass_file = str(tmpdir.join('filter_qs.yaml')) diff --git a/tests/integration/test_matchers.py b/tests/integration/test_matchers.py index 5ead41f..396bb40 100644 --- a/tests/integration/test_matchers.py +++ b/tests/integration/test_matchers.py @@ -37,7 +37,7 @@ def cassette(tmpdir): ('query', 'https://google.com/get?p2=q2&p1=q1', 'http://httpbin.org/get?p1=q1&a=b') - ]) +]) def test_matchers(cassette, matcher, matching_uri, not_matching_uri): # play cassette with default uri with vcr.use_cassette(cassette, match_on=[matcher]) as cass: diff --git a/tests/integration/test_record_mode.py b/tests/integration/test_record_mode.py index 3b0204e..5d9b603 100644 --- a/tests/integration/test_record_mode.py +++ b/tests/integration/test_record_mode.py @@ -1,4 +1,3 @@ -import os import pytest import vcr from six.moves.urllib.request import urlopen @@ -8,39 +7,39 @@ def test_once_record_mode(tmpdir): testfile = str(tmpdir.join('recordmode.yml')) with vcr.use_cassette(testfile, record_mode="once"): # cassette file doesn't exist, so create. - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() - with vcr.use_cassette(testfile, record_mode="once") as cass: + with vcr.use_cassette(testfile, record_mode="once"): # make the same request again - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() # the first time, it's played from the cassette. # but, try to access something else from the same cassette, and an # exception is raised. with pytest.raises(Exception): - response = urlopen('http://httpbin.org/get').read() + urlopen('http://httpbin.org/get').read() def test_once_record_mode_two_times(tmpdir): testfile = str(tmpdir.join('recordmode.yml')) with vcr.use_cassette(testfile, record_mode="once"): # get two of the same file - response1 = urlopen('http://httpbin.org/').read() - response2 = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() - with vcr.use_cassette(testfile, record_mode="once") as cass: + with vcr.use_cassette(testfile, record_mode="once"): # do it again - response = urlopen('http://httpbin.org/').read() - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() def test_once_mode_three_times(tmpdir): testfile = str(tmpdir.join('recordmode.yml')) with vcr.use_cassette(testfile, record_mode="once"): # get three of the same file - response1 = urlopen('http://httpbin.org/').read() - response2 = urlopen('http://httpbin.org/').read() - response2 = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() def test_new_episodes_record_mode(tmpdir): @@ -48,18 +47,18 @@ def test_new_episodes_record_mode(tmpdir): with vcr.use_cassette(testfile, record_mode="new_episodes"): # cassette file doesn't exist, so create. - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() with vcr.use_cassette(testfile, record_mode="new_episodes") as cass: # make the same request again - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() # all responses have been played assert cass.all_played # in the "new_episodes" record mode, we can add more requests to # a cassette without repurcussions. - response = urlopen('http://httpbin.org/get').read() + urlopen('http://httpbin.org/get').read() # one of the responses has been played assert cass.play_count == 1 @@ -102,15 +101,15 @@ def test_all_record_mode(tmpdir): with vcr.use_cassette(testfile, record_mode="all"): # cassette file doesn't exist, so create. - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() with vcr.use_cassette(testfile, record_mode="all") as cass: # make the same request again - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() # in the "all" record mode, we can add more requests to # a cassette without repurcussions. - response = urlopen('http://httpbin.org/get').read() + urlopen('http://httpbin.org/get').read() # The cassette was never actually played, even though it existed. # that's because, in "all" mode, the requests all go directly to @@ -124,7 +123,7 @@ def test_none_record_mode(tmpdir): testfile = str(tmpdir.join('recordmode.yml')) with vcr.use_cassette(testfile, record_mode="none"): with pytest.raises(Exception): - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() def test_none_record_mode_with_existing_cassette(tmpdir): @@ -132,12 +131,12 @@ def test_none_record_mode_with_existing_cassette(tmpdir): testfile = str(tmpdir.join('recordmode.yml')) with vcr.use_cassette(testfile, record_mode="all"): - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() # play from cassette file with vcr.use_cassette(testfile, record_mode="none") as cass: - response = urlopen('http://httpbin.org/').read() + urlopen('http://httpbin.org/').read() assert cass.play_count == 1 # but if I try to hit the net, raise an exception. with pytest.raises(Exception): - response = urlopen('http://httpbin.org/get').read() + urlopen('http://httpbin.org/get').read() diff --git a/tests/integration/test_register_matcher.py b/tests/integration/test_register_matcher.py index ad1da1c..ed83afd 100644 --- a/tests/integration/test_register_matcher.py +++ b/tests/integration/test_register_matcher.py @@ -14,12 +14,12 @@ def test_registered_true_matcher(tmpdir): my_vcr = vcr.VCR() my_vcr.register_matcher('true', true_matcher) testfile = str(tmpdir.join('test.yml')) - with my_vcr.use_cassette(testfile, match_on=['true']) as cass: + with my_vcr.use_cassette(testfile, match_on=['true']): # These 2 different urls are stored as the same request urlopen('http://httpbin.org/') urlopen('https://httpbin.org/get') - with my_vcr.use_cassette(testfile, match_on=['true']) as cass: + with my_vcr.use_cassette(testfile, match_on=['true']): # I can get the response twice even though I only asked for it once urlopen('http://httpbin.org/get') urlopen('https://httpbin.org/get') diff --git a/tests/integration/test_register_serializer.py b/tests/integration/test_register_serializer.py index a7d15bc..734f301 100644 --- a/tests/integration/test_register_serializer.py +++ b/tests/integration/test_register_serializer.py @@ -10,7 +10,7 @@ class MockSerializer(object): def deserialize(self, cassette_string): self.serialize_count += 1 self.cassette_string = cassette_string - return {'interactions':[]} + return {'interactions': []} def serialize(self, cassette_dict): self.deserialize_count += 1 diff --git a/tests/integration/test_requests.py b/tests/integration/test_requests.py index 674f6ed..58ce543 100644 --- a/tests/integration/test_requests.py +++ b/tests/integration/test_requests.py @@ -44,6 +44,7 @@ def test_body(tmpdir, scheme): with vcr.use_cassette(str(tmpdir.join('body.yaml'))): assert content == requests.get(url).content + def test_effective_url(scheme, tmpdir): '''Ensure that the effective_url is captured''' url = scheme + '://httpbin.org/redirect-to?url=/html' @@ -54,6 +55,7 @@ def test_effective_url(scheme, tmpdir): with vcr.use_cassette(str(tmpdir.join('url.yaml'))): assert effective_url == requests.get(url).url + def test_auth(tmpdir, scheme): '''Ensure that we can handle basic auth''' auth = ('user', 'passwd') @@ -242,4 +244,3 @@ def test_filter_post_params(tmpdir, scheme): requests.post(url, data={'key': 'value'}) with vcr.use_cassette(cass_loc, filter_post_data_parameters=['key']) as cass: assert b'key=value' not in cass.requests[0].body - diff --git a/tests/integration/test_stubs.py b/tests/integration/test_stubs.py index 15918d2..2b069ea 100644 --- a/tests/integration/test_stubs.py +++ b/tests/integration/test_stubs.py @@ -1,6 +1,7 @@ import vcr import six.moves.http_client as httplib + def _headers_are_case_insensitive(): conn = httplib.HTTPConnection('httpbin.org') conn.request('GET', "/cookies/set?k1=v1") @@ -12,6 +13,7 @@ def _headers_are_case_insensitive(): cookie_data2 = r2.getheader('Set-Cookie') return cookie_data1 == cookie_data2 + def test_case_insensitivity(tmpdir): testfile = str(tmpdir.join('case_insensitivity.yml')) # check if headers are case insensitive outside of vcrpy @@ -25,12 +27,14 @@ def test_case_insensitivity(tmpdir): # behavior should be the same both inside and outside assert outside == inside == inside2 + def _multiple_header_value(httpserver): conn = httplib.HTTPConnection('%s:%s' % httpserver.server_address) conn.request('GET', "/") r = conn.getresponse() return r.getheader('foo') + def test_multiple_headers(tmpdir, httpserver): testfile = str(tmpdir.join('multiple_headers.yaml')) httpserver.serve_content('Hello!', headers=[('foo', 'bar'), ('foo', 'baz')]) diff --git a/tests/integration/test_tornado.py b/tests/integration/test_tornado.py index b7d3c4e..ba23260 100644 --- a/tests/integration/test_tornado.py +++ b/tests/integration/test_tornado.py @@ -81,6 +81,7 @@ def test_body(get_client, tmpdir, scheme): assert content == (yield get(get_client(), url)).body assert 1 == cass.play_count + @pytest.mark.gen_test def test_effective_url(get_client, scheme, tmpdir): '''Ensure that the effective_url is captured''' @@ -93,6 +94,7 @@ def test_effective_url(get_client, scheme, tmpdir): assert effective_url == (yield get(get_client(), url)).effective_url assert 1 == cass.play_count + @pytest.mark.gen_test def test_auth(get_client, tmpdir, scheme): '''Ensure that we can handle basic auth''' diff --git a/tests/integration/test_urllib2.py b/tests/integration/test_urllib2.py index 6754303..be1adc4 100644 --- a/tests/integration/test_urllib2.py +++ b/tests/integration/test_urllib2.py @@ -22,43 +22,46 @@ def scheme(request): def test_response_code(scheme, tmpdir): '''Ensure we can read a response code from a fetch''' url = scheme + '://httpbin.org/' - with vcr.use_cassette(str(tmpdir.join('atts.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('atts.yaml'))): code = urlopen(url).getcode() - with vcr.use_cassette(str(tmpdir.join('atts.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('atts.yaml'))): assert code == urlopen(url).getcode() def test_random_body(scheme, tmpdir): '''Ensure we can read the content, and that it's served from cache''' url = scheme + '://httpbin.org/bytes/1024' - with vcr.use_cassette(str(tmpdir.join('body.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('body.yaml'))): body = urlopen(url).read() - with vcr.use_cassette(str(tmpdir.join('body.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('body.yaml'))): assert body == urlopen(url).read() def test_response_headers(scheme, tmpdir): '''Ensure we can get information from the response''' url = scheme + '://httpbin.org/' - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): open1 = urlopen(url).info().items() - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): open2 = urlopen(url).info().items() + assert sorted(open1) == sorted(open2) + def test_effective_url(scheme, tmpdir): '''Ensure that the effective_url is captured''' url = scheme + '://httpbin.org/redirect-to?url=/html' - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): effective_url = urlopen(url).geturl() assert effective_url == scheme + '://httpbin.org/html' - with vcr.use_cassette(str(tmpdir.join('headers.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('headers.yaml'))): assert effective_url == urlopen(url).geturl() + def test_multiple_requests(scheme, tmpdir): '''Ensure that we can cache multiple requests''' urls = [ @@ -76,10 +79,10 @@ def test_get_data(scheme, tmpdir): '''Ensure that it works with query data''' data = urlencode({'some': 1, 'data': 'here'}) url = scheme + '://httpbin.org/get?' + data - with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))): res1 = urlopen(url).read() - with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('get_data.yaml'))): res2 = urlopen(url).read() assert res1 == res2 @@ -89,11 +92,12 @@ def test_post_data(scheme, tmpdir): '''Ensure that it works when posting data''' data = urlencode({'some': 1, 'data': 'here'}).encode('utf-8') url = scheme + '://httpbin.org/post' - with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))): res1 = urlopen(url, data).read() with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: res2 = urlopen(url, data).read() + assert len(cass) == 1 assert res1 == res2 assert_cassette_has_one_response(cass) @@ -103,10 +107,13 @@ def test_post_unicode_data(scheme, tmpdir): '''Ensure that it works when posting unicode data''' data = urlencode({'snowman': u'☃'.encode('utf-8')}).encode('utf-8') url = scheme + '://httpbin.org/post' - with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: + with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))): res1 = urlopen(url, data).read() + with vcr.use_cassette(str(tmpdir.join('post_data.yaml'))) as cass: res2 = urlopen(url, data).read() + assert len(cass) == 1 + assert res1 == res2 assert_cassette_has_one_response(cass) @@ -122,6 +129,7 @@ def test_cross_scheme(tmpdir): assert len(cass) == 2 assert cass.play_count == 0 + def test_decorator(scheme, tmpdir): '''Test the decorator version of VCR.py''' url = scheme + '://httpbin.org/' diff --git a/tests/integration/test_urllib3.py b/tests/integration/test_urllib3.py index 694416f..2a3665c 100644 --- a/tests/integration/test_urllib3.py +++ b/tests/integration/test_urllib3.py @@ -20,7 +20,7 @@ def scheme(request): @pytest.fixture(scope='module') def verify_pool_mgr(): return urllib3.PoolManager( - cert_reqs='CERT_REQUIRED', # Force certificate check. + cert_reqs='CERT_REQUIRED', # Force certificate check. ca_certs=certifi.where() ) diff --git a/tests/integration/test_wild.py b/tests/integration/test_wild.py index 2d446fb..47edc08 100644 --- a/tests/integration/test_wild.py +++ b/tests/integration/test_wild.py @@ -42,6 +42,8 @@ def test_flickr_multipart_upload(): data = r.read() h.close() + return data + with vcr.use_cassette('fixtures/vcr_cassettes/flickr.yaml') as cass: _pretend_to_be_flickr_library() assert len(cass) == 1 @@ -63,7 +65,8 @@ def test_cookies(tmpdir): testfile = str(tmpdir.join('cookies.yml')) with vcr.use_cassette(testfile): s = requests.Session() - r1 = s.get("http://httpbin.org/cookies/set?k1=v1&k2=v2") + s.get("http://httpbin.org/cookies/set?k1=v1&k2=v2") + r2 = s.get("http://httpbin.org/cookies") assert len(r2.json()['cookies']) == 2 @@ -81,9 +84,8 @@ def test_xmlrpclib(tmpdir): roundup_server = xmlrpc_client.ServerProxy('http://bugs.python.org/xmlrpc', allow_none=True) original_schema = roundup_server.schema() - with vcr.use_cassette(str(tmpdir.join('xmlrpcvideo.yaml'))) as cassette: + with vcr.use_cassette(str(tmpdir.join('xmlrpcvideo.yaml'))): roundup_server = xmlrpc_client.ServerProxy('http://bugs.python.org/xmlrpc', allow_none=True) second_schema = roundup_server.schema() assert original_schema == second_schema - diff --git a/tests/unit/test_cassettes.py b/tests/unit/test_cassettes.py index 413b154..fc7fac0 100644 --- a/tests/unit/test_cassettes.py +++ b/tests/unit/test_cassettes.py @@ -89,7 +89,7 @@ def make_get_request(): def test_function_decorated_with_use_cassette_can_be_invoked_multiple_times(*args): decorated_function = Cassette.use(path='test')(make_get_request) for i in range(4): - decorated_function() + decorated_function() def test_arg_getter_functionality(): @@ -160,7 +160,7 @@ def test_nesting_cassette_context_managers(*args): with contextlib.ExitStack() as exit_stack: first_cassette = exit_stack.enter_context(Cassette.use(path='test')) exit_stack.enter_context(mock.patch.object(first_cassette, 'play_response', - return_value=first_response)) + return_value=first_response)) assert_get_response_body_is('first_response') # Make sure a second cassette can supercede the first @@ -200,16 +200,17 @@ def test_custom_patchers(): custom_patches=((Test, 'attribute', VCRHTTPSConnection),)): assert issubclass(Test.attribute, VCRHTTPSConnection) assert VCRHTTPSConnection is not Test.attribute - assert Test.attribute is not old_attribute + assert Test.attribute is not old_attribute assert issubclass(Test.attribute, VCRHTTPSConnection) assert VCRHTTPSConnection is not Test.attribute - assert Test.attribute is old_attribute + assert Test.attribute is old_attribute def test_decorated_functions_are_reentrant(): info = {"second": False} original_conn = httplib.HTTPConnection + @Cassette.use(path='whatever', inject=True) def test_function(cassette): if info['second']: @@ -219,6 +220,7 @@ def test_decorated_functions_are_reentrant(): info['second'] = True test_function() assert httplib.HTTPConnection is info['first_conn'] + test_function() assert httplib.HTTPConnection is original_conn @@ -232,9 +234,11 @@ def test_cassette_use_called_without_path_uses_function_to_generate_path(): def test_path_transformer_with_function_path(): path_transformer = lambda path: os.path.join('a', path) + @Cassette.use(inject=True, path_transformer=path_transformer) def function_name(cassette): assert cassette._path == os.path.join('a', 'function_name') + function_name() @@ -255,15 +259,18 @@ def test_path_transformer_None(): def test_func_path_generator(): def generator(function): return os.path.join(os.path.dirname(inspect.getfile(function)), - function.__name__) + function.__name__) + @Cassette.use(inject=True, func_path_generator=generator) def function_name(cassette): assert cassette._path == os.path.join(os.path.dirname(__file__), 'function_name') + function_name() def test_use_as_decorator_on_coroutine(): original_http_connetion = httplib.HTTPConnection + @Cassette.use(inject=True) def test_function(cassette): assert httplib.HTTPConnection.cassette is cassette @@ -274,6 +281,7 @@ def test_use_as_decorator_on_coroutine(): assert httplib.HTTPConnection is not original_http_connetion value = yield 2 assert value == 2 + coroutine = test_function() value = next(coroutine) while True: @@ -285,6 +293,7 @@ def test_use_as_decorator_on_coroutine(): def test_use_as_decorator_on_generator(): original_http_connetion = httplib.HTTPConnection + @Cassette.use(inject=True) def test_function(cassette): assert httplib.HTTPConnection.cassette is cassette @@ -293,4 +302,5 @@ def test_use_as_decorator_on_generator(): assert httplib.HTTPConnection.cassette is cassette assert httplib.HTTPConnection is not original_http_connetion yield 2 + assert list(test_function()) == [1, 2] diff --git a/tests/unit/test_request.py b/tests/unit/test_request.py index a89e15a..dfd68d7 100644 --- a/tests/unit/test_request.py +++ b/tests/unit/test_request.py @@ -29,9 +29,9 @@ def test_add_header_deprecated(): ('https://go.com/', 443), ('https://go.com:443/', 443), ('https://go.com:3000/', 3000), - ]) +]) def test_port(uri, expected_port): - req = Request('GET', uri, '', {}) + req = Request('GET', uri, '', {}) assert req.port == expected_port diff --git a/tests/unit/test_stubs.py b/tests/unit/test_stubs.py index 7e51450..a3b7cca 100644 --- a/tests/unit/test_stubs.py +++ b/tests/unit/test_stubs.py @@ -1,6 +1,8 @@ from vcr.stubs import VCRHTTPSConnection + class TestVCRConnection(object): + def test_setting_of_attributes_get_propogated_to_real_connection(self): vcr_connection = VCRHTTPSConnection('www.examplehost.com') vcr_connection.ssl_version = 'example_ssl_version' diff --git a/tox.ini b/tox.ini index 5e1a0dd..88bea53 100644 --- a/tox.ini +++ b/tox.ini @@ -1,15 +1,22 @@ [tox] -envlist = {py26,py27,py33,py34,pypy}-{requests27,requests26,requests25,requests24,requests23,requests22,requests1,httplib2,urllib317,urllib319,urllib3110,tornado,boto} +envlist = py34-flakes,{py26,py27,py33,py34,pypy}-{requests27,requests26,requests25,requests24,requests23,requests22,requests1,httplib2,urllib317,urllib319,urllib3110,tornado,boto} + +[testenv:py34-flakes] +skipsdist = True +commands = + flake8 --exclude="./docs/conf.py" + pyflakes ./docs/conf.py +deps = flake8 [testenv] -commands = - py.test {posargs} basepython = py26: python2.6 py27: python2.7 py33: python3.3 py34: python3.4 pypy: pypy +commands = + py.test {posargs} deps = mock pytest @@ -30,3 +37,6 @@ deps = {py26,py27,py33,py34,pypy}-tornado: pytest-tornado {py26,py27,py33,py34}-tornado: pycurl boto: boto + +[flake8] +max_line_length = 110 diff --git a/vcr/matchers.py b/vcr/matchers.py index 57e7a02..b54ed2f 100644 --- a/vcr/matchers.py +++ b/vcr/matchers.py @@ -67,7 +67,8 @@ def _identity(x): def _get_transformer(request): for checker, transformer in _checker_transformer_pairs: - if checker(request.headers): return transformer + if checker(request.headers): + return transformer else: return _identity diff --git a/vcr/migration.py b/vcr/migration.py index 9e423f8..6e30027 100644 --- a/vcr/migration.py +++ b/vcr/migration.py @@ -19,7 +19,7 @@ import sys import tempfile import yaml -from .serializers import compat, yamlserializer, jsonserializer +from .serializers import yamlserializer, jsonserializer from .serialize import serialize from . import request from .stubs.compat import get_httpmessage diff --git a/vcr/patch.py b/vcr/patch.py index 8400c68..b4b5e0e 100644 --- a/vcr/patch.py +++ b/vcr/patch.py @@ -59,7 +59,7 @@ except ImportError: # pragma: no cover pass else: _SimpleAsyncHTTPClient_fetch_impl = \ - tornado.simple_httpclient.SimpleAsyncHTTPClient.fetch_impl + tornado.simple_httpclient.SimpleAsyncHTTPClient.fetch_impl try: @@ -68,7 +68,7 @@ except ImportError: # pragma: no cover pass else: _CurlAsyncHTTPClient_fetch_impl = \ - tornado.curl_httpclient.CurlAsyncHTTPClient.fetch_impl + tornado.curl_httpclient.CurlAsyncHTTPClient.fetch_impl class CassettePatcherBuilder(object): @@ -127,13 +127,13 @@ class CassettePatcherBuilder(object): described in the previous paragraph. """ if isinstance(replacement_dict_or_obj, dict): - for key, replacement_obj in replacement_dict_or_obj.items(): + for key, replacement_obj in replacement_dict_or_obj.items(): replacement_obj = self._recursively_apply_get_cassette_subclass( replacement_obj) replacement_dict_or_obj[key] = replacement_obj return replacement_dict_or_obj if hasattr(replacement_dict_or_obj, 'cassette'): - replacement_dict_or_obj = self._get_cassette_subclass( + replacement_dict_or_obj = self._get_cassette_subclass( replacement_dict_or_obj) return replacement_dict_or_obj @@ -147,7 +147,7 @@ class CassettePatcherBuilder(object): def _build_cassette_subclass(self, base_class): bases = (base_class,) - if not issubclass(base_class, object): # Check for old style class + if not issubclass(base_class, object): # Check for old style class bases += (object,) return type('{0}{1}'.format(base_class.__name__, self._cassette._path), bases, dict(cassette=self._cassette)) @@ -167,11 +167,13 @@ class CassettePatcherBuilder(object): def _patched_get_conn(self, connection_pool_class, connection_class_getter): get_conn = connection_pool_class._get_conn + @functools.wraps(get_conn) def patched_get_conn(pool, timeout=None): connection = get_conn(pool, timeout) - connection_class = pool.ConnectionCls if hasattr(pool, 'ConnectionCls') \ - else connection_class_getter() + connection_class = ( + pool.ConnectionCls if hasattr(pool, 'ConnectionCls') + else connection_class_getter()) # We need to make sure that we are actually providing a # patched version of the connection class. This might not # always be the case because the pool keeps previously @@ -181,15 +183,18 @@ class CassettePatcherBuilder(object): while not isinstance(connection, connection_class): connection = get_conn(pool, timeout) return connection + return patched_get_conn def _patched_new_conn(self, connection_pool_class, connection_remover): new_conn = connection_pool_class._new_conn + @functools.wraps(new_conn) def patched_new_conn(pool): new_connection = new_conn(pool) connection_remover.add_connection_to_pool_entry(pool, new_connection) return new_connection + return patched_new_conn def _urllib3(self): @@ -270,10 +275,10 @@ class CassettePatcherBuilder(object): # connections of the appropriate type. mock_triples += ((cpool.HTTPConnectionPool, '_get_conn', self._patched_get_conn(cpool.HTTPConnectionPool, - lambda : cpool.HTTPConnection)), + lambda: cpool.HTTPConnection)), (cpool.HTTPSConnectionPool, '_get_conn', self._patched_get_conn(cpool.HTTPSConnectionPool, - lambda : cpool.HTTPSConnection)), + lambda: cpool.HTTPSConnection)), (cpool.HTTPConnectionPool, '_new_conn', self._patched_new_conn(cpool.HTTPConnectionPool, http_connection_remover)), @@ -382,7 +387,7 @@ def reset_patchers(): else: yield mock.patch.object( curl.CurlAsyncHTTPClient, - 'fetch_impl', + 'fetch_impl', _CurlAsyncHTTPClient_fetch_impl, ) diff --git a/vcr/stubs/__init__.py b/vcr/stubs/__init__.py index e140945..b372658 100644 --- a/vcr/stubs/__init__.py +++ b/vcr/stubs/__init__.py @@ -1,9 +1,5 @@ '''Stubs for patching HTTP and HTTPS requests''' -try: - import http.client -except ImportError: - pass import logging import six from six.moves.http_client import ( @@ -329,8 +325,8 @@ class VCRConnection(object): try: setattr(self.real_connection, name, value) except AttributeError: - # raised if real_connection has not been set yet, such as when - # we're setting the real_connection itself for the first time + # raised if real_connection has not been set yet, such as when + # we're setting the real_connection itself for the first time pass super(VCRConnection, self).__setattr__(name, value) diff --git a/vcr/stubs/requests_stubs.py b/vcr/stubs/requests_stubs.py index 30e960f..8cae533 100644 --- a/vcr/stubs/requests_stubs.py +++ b/vcr/stubs/requests_stubs.py @@ -10,8 +10,10 @@ from ..stubs import VCRHTTPConnection, VCRHTTPSConnection # urllib3 defines its own HTTPConnection classes, which requests goes ahead and assumes # you're using. It includes some polyfills for newer features missing in older pythons. + class VCRRequestsHTTPConnection(VCRHTTPConnection, HTTPConnection): _baseclass = HTTPConnection + class VCRRequestsHTTPSConnection(VCRHTTPSConnection, VerifiedHTTPSConnection): _baseclass = VerifiedHTTPSConnection diff --git a/vcr/stubs/urllib3_stubs.py b/vcr/stubs/urllib3_stubs.py index 214884d..dff38d1 100644 --- a/vcr/stubs/urllib3_stubs.py +++ b/vcr/stubs/urllib3_stubs.py @@ -6,8 +6,10 @@ from ..stubs import VCRHTTPConnection, VCRHTTPSConnection # urllib3 defines its own HTTPConnection classes. It includes some polyfills # for newer features missing in older pythons. + class VCRRequestsHTTPConnection(VCRHTTPConnection, HTTPConnection): _baseclass = HTTPConnection + class VCRRequestsHTTPSConnection(VCRHTTPSConnection, VerifiedHTTPSConnection): _baseclass = VerifiedHTTPSConnection diff --git a/vcr/util.py b/vcr/util.py index e126197..2e6effb 100644 --- a/vcr/util.py +++ b/vcr/util.py @@ -71,6 +71,7 @@ class CaseInsensitiveDict(collections.MutableMapping): def __repr__(self): return str(dict(self.items())) + def partition_dict(predicate, dictionary): true_dict = {} false_dict = {} @@ -89,6 +90,7 @@ def compose(*functions): return res return composed + def read_body(request): if hasattr(request.body, 'read'): return request.body.read()