Hello community, here is the log from the commit of package python-vcrpy for openSUSE:Factory checked in at 2018-10-26 11:08:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-vcrpy (Old) and /work/SRC/openSUSE:Factory/.python-vcrpy.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-vcrpy" Fri Oct 26 11:08:39 2018 rev:2 rq:644399 version:2.0.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-vcrpy/python-vcrpy.changes 2017-08-30 16:23:59.354855452 +0200 +++ /work/SRC/openSUSE:Factory/.python-vcrpy.new/python-vcrpy.changes 2018-10-26 11:08:47.765839974 +0200 @@ -1,0 +2,11 @@ +Wed Oct 24 15:24:59 UTC 2018 - Jan Engelhardt <[email protected]> + +- Use noun phrase in summary and adjust descriptions. + +------------------------------------------------------------------- +Wed Oct 24 13:31:40 UTC 2018 - Tomáš Chvátal <[email protected]> + +- Version update to 2.0.1: + * Support python 3.7 (fix httplib2 and urllib2, thanks @felixonmars) + +------------------------------------------------------------------- Old: ---- vcrpy-1.11.1.tar.gz New: ---- vcrpy-2.0.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-vcrpy.spec ++++++ --- /var/tmp/diff_new_pack.Uisx2r/_old 2018-10-26 11:08:51.381834963 +0200 +++ /var/tmp/diff_new_pack.Uisx2r/_new 2018-10-26 11:08:51.385834957 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-vcrpy # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # Copyright (c) 2015 LISA GmbH, Bingen, Germany. # # All modifications and additions to the file contributed by third parties @@ -13,37 +13,34 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} -%bcond_without test Name: python-vcrpy -Version: 1.11.1 +Version: 2.0.1 Release: 0 -Summary: Automatically mock your HTTP interactions to simplify and speed up testing +Summary: Python module to mock and replay HTTP interactions License: MIT Group: Development/Languages/Python -Url: https://github.com/kevin1024/vcrpy +URL: https://github.com/kevin1024/vcrpy Source: https://files.pythonhosted.org/packages/source/v/vcrpy/vcrpy-%{version}.tar.gz -BuildRequires: %{python_module devel} -BuildRequires: %{python_module setuptools} -BuildRequires: fdupes -BuildRequires: python-rpm-macros -%if %{with test} BuildRequires: %{python_module PyYAML} BuildRequires: %{python_module pytest-httpbin} BuildRequires: %{python_module pytest} +BuildRequires: %{python_module setuptools} BuildRequires: %{python_module six >= 1.5} BuildRequires: %{python_module wrapt} +BuildRequires: fdupes +BuildRequires: python-rpm-macros BuildRequires: python2-contextlib2 BuildRequires: python2-mock BuildRequires: python3-yarl -%endif Requires: python-PyYAML Requires: python-six >= 1.5 Requires: python-wrapt +BuildArch: noarch %ifpython2 Requires: python2-contextlib2 Requires: python2-mock @@ -51,14 +48,11 @@ %ifpython3 Requires: python3-yarl %endif -BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildArch: noarch - %python_subpackages %description -Record your test suite's HTTP interactions and replay them during future test -runs for fast, deterministic, accurate tests. +This module records a test suite's HTTP interactions and replays them during future +test runs for deterministic tests. This is a Python version of Ruby's VCR library. @@ -72,16 +66,14 @@ %python_install %python_expand %fdupes %{buildroot}%{$python_sitelib}/vcr -%if %{with test} %check # Skip TestVCRConnection.testing_connect. Attempts # a real connection. %python_exec -m pytest -k "not testing_connect" tests -%endif %files %{python_files} -%defattr(-,root,root,-) -%doc LICENSE.txt README.rst +%license LICENSE.txt +%doc README.rst %{python_sitelib}/* %changelog ++++++ vcrpy-1.11.1.tar.gz -> vcrpy-2.0.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/PKG-INFO new/vcrpy-2.0.1/PKG-INFO --- old/vcrpy-1.11.1/PKG-INFO 2017-05-28 04:48:36.000000000 +0200 +++ new/vcrpy-2.0.1/PKG-INFO 2018-09-23 20:38:58.000000000 +0200 @@ -1,12 +1,12 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: vcrpy -Version: 1.11.1 +Version: 2.0.1 Summary: Automatically mock your HTTP interactions to simplify and speed up testing Home-page: https://github.com/kevin1024/vcrpy Author: Kevin McCarthy Author-email: [email protected] License: MIT -Description: |PyPI| |Build Status| |Waffle Ready| |Gitter| +Description: |PyPI| |Python versions| |Build Status| |Waffle Ready| |Gitter| VCR.py ====== @@ -49,20 +49,6 @@ all HTTP interactions, which will update them to correspond to the new API. - Support - ------- - - VCR.py works great with the following HTTP clients: - - - requests - - aiohttp - - urllib3 - - tornado - - urllib2 - - boto - - boto3 - - License ======= @@ -70,10 +56,12 @@ more details .. |PyPI| image:: https://img.shields.io/pypi/v/vcrpy.svg - :target: https://pypi.python.org/pypi/vcrpy-unittest - .. |Build Status| image:: https://secure.travis-ci.org/kevin1024/vcrpy.png?branch=master + :target: https://pypi.python.org/pypi/vcrpy + .. |Python versions| image:: https://img.shields.io/pypi/pyversions/vcrpy.svg + :target: https://pypi.python.org/pypi/vcrpy + .. |Build Status| image:: https://secure.travis-ci.org/kevin1024/vcrpy.svg?branch=master :target: http://travis-ci.org/kevin1024/vcrpy - .. |Waffle Ready| image:: https://badge.waffle.io/kevin1024/vcrpy.png?label=ready&title=waffle + .. |Waffle Ready| image:: https://badge.waffle.io/kevin1024/vcrpy.svg?label=ready&title=waffle :target: https://waffle.io/kevin1024/vcrpy .. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg :alt: Join the chat at https://gitter.im/kevin1024/vcrpy @@ -84,7 +72,16 @@ Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Testing Classifier: Topic :: Internet :: WWW/HTTP Classifier: License :: OSI Approved :: MIT License +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/README.rst new/vcrpy-2.0.1/README.rst --- old/vcrpy-1.11.1/README.rst 2016-08-14 22:39:58.000000000 +0200 +++ new/vcrpy-2.0.1/README.rst 2018-09-19 15:58:31.000000000 +0200 @@ -1,4 +1,4 @@ -|PyPI| |Build Status| |Waffle Ready| |Gitter| +|PyPI| |Python versions| |Build Status| |Waffle Ready| |Gitter| VCR.py ====== @@ -41,20 +41,6 @@ all HTTP interactions, which will update them to correspond to the new API. -Support -------- - -VCR.py works great with the following HTTP clients: - -- requests -- aiohttp -- urllib3 -- tornado -- urllib2 -- boto -- boto3 - - License ======= @@ -62,10 +48,12 @@ more details .. |PyPI| image:: https://img.shields.io/pypi/v/vcrpy.svg - :target: https://pypi.python.org/pypi/vcrpy-unittest -.. |Build Status| image:: https://secure.travis-ci.org/kevin1024/vcrpy.png?branch=master + :target: https://pypi.python.org/pypi/vcrpy +.. |Python versions| image:: https://img.shields.io/pypi/pyversions/vcrpy.svg + :target: https://pypi.python.org/pypi/vcrpy +.. |Build Status| image:: https://secure.travis-ci.org/kevin1024/vcrpy.svg?branch=master :target: http://travis-ci.org/kevin1024/vcrpy -.. |Waffle Ready| image:: https://badge.waffle.io/kevin1024/vcrpy.png?label=ready&title=waffle +.. |Waffle Ready| image:: https://badge.waffle.io/kevin1024/vcrpy.svg?label=ready&title=waffle :target: https://waffle.io/kevin1024/vcrpy .. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg :alt: Join the chat at https://gitter.im/kevin1024/vcrpy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/setup.cfg new/vcrpy-2.0.1/setup.cfg --- old/vcrpy-1.11.1/setup.cfg 2017-05-28 04:48:36.000000000 +0200 +++ new/vcrpy-2.0.1/setup.cfg 2018-09-23 20:38:58.000000000 +0200 @@ -2,7 +2,6 @@ universal = 1 [egg_info] -tag_svn_revision = 0 tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/setup.py new/vcrpy-2.0.1/setup.py --- old/vcrpy-1.11.1/setup.py 2017-05-28 04:47:05.000000000 +0200 +++ new/vcrpy-2.0.1/setup.py 2018-09-23 20:23:07.000000000 +0200 @@ -1,11 +1,9 @@ #!/usr/bin/env python import sys -import logging from setuptools import setup, find_packages from setuptools.command.test import test as TestCommand -import pkg_resources long_description = open('README.rst', 'r').read() @@ -24,31 +22,14 @@ sys.exit(errno) -install_requires = ['PyYAML', 'wrapt', 'six>=1.5'] - - -extras_require = { - ':python_version in "2.4, 2.5, 2.6"': - ['contextlib2', 'backport_collections', 'mock'], - ':python_version in "2.7, 3.1, 3.2"': ['contextlib2', 'mock'], - ':python_version in "3.4, 3.5, 3.6"': ['yarl'], -} - - -try: - if 'bdist_wheel' not in sys.argv: - for key, value in extras_require.items(): - if key.startswith(':') and pkg_resources.evaluate_marker(key[1:]): - install_requires.extend(value) -except Exception: - logging.getLogger(__name__).exception( - 'Something went wrong calculating platform specific dependencies, so ' - "you're getting them all!" - ) - for key, value in extras_require.items(): - if key.startswith(':'): - install_requires.extend(value) - +install_requires = [ + 'PyYAML', + 'wrapt', + 'six>=1.5', + 'contextlib2; python_version=="2.7"', + 'mock; python_version=="2.7"', + 'yarl; python_version>="3.4"', +] excluded_packages = ["tests*"] if sys.version_info[0] == 2: @@ -56,7 +37,7 @@ setup( name='vcrpy', - version='1.11.1', + version='2.0.1', description=( "Automatically mock your HTTP interactions to simplify and " "speed up testing" @@ -66,8 +47,8 @@ author_email='[email protected]', url='https://github.com/kevin1024/vcrpy', packages=find_packages(exclude=excluded_packages), + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', install_requires=install_requires, - extras_require=extras_require, license='MIT', tests_require=['pytest', 'mock', 'pytest-httpbin'], classifiers=[ @@ -75,7 +56,15 @@ 'Environment :: Console', 'Intended Audience :: Developers', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development :: Testing', 'Topic :: Internet :: WWW/HTTP', 'License :: OSI Approved :: MIT License', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/aiohttp_utils.py new/vcrpy-2.0.1/tests/integration/aiohttp_utils.py --- old/vcrpy-1.11.1/tests/integration/aiohttp_utils.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/aiohttp_utils.py 2018-09-19 15:58:31.000000000 +0200 @@ -1,13 +1,33 @@ +# flake8: noqa import asyncio + import aiohttp +from aiohttp.test_utils import TestClient + + +async def aiohttp_request(loop, method, url, output='text', encoding='utf-8', content_type=None, **kwargs): + session = aiohttp.ClientSession(loop=loop) + response_ctx = session.request(method, url, **kwargs) + + response = await response_ctx.__aenter__() + if output == 'text': + content = await response.text() + elif output == 'json': + content_type = content_type or 'application/json' + content = await response.json(encoding=encoding, content_type=content_type) + elif output == 'raw': + content = await response.read() + + response_ctx._resp.close() + await session.close() + + return response, content + +def aiohttp_app(): + async def hello(request): + return aiohttp.web.Response(text='hello') [email protected] -def aiohttp_request(loop, method, url, as_text, **kwargs): - with aiohttp.ClientSession(loop=loop) as session: - response = yield from session.request(method, url, **kwargs) # NOQA: E999 - if as_text: - content = yield from response.text() # NOQA: E999 - else: - content = yield from response.json() # NOQA: E999 - return response, content + app = aiohttp.web.Application() + app.router.add_get('/', hello) + return app diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/async_def.py new/vcrpy-2.0.1/tests/integration/async_def.py --- old/vcrpy-1.11.1/tests/integration/async_def.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/async_def.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,13 +0,0 @@ -import aiohttp -import pytest -import vcr - - [email protected]_cassette() [email protected] -async def test_http(): # noqa: E999 - async with aiohttp.ClientSession() as session: - url = 'https://httpbin.org/get' - params = {'ham': 'spam'} - resp = await session.get(url, params=params) # noqa: E999 - assert (await resp.json())['args'] == {'ham': 'spam'} # noqa: E999 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_aiohttp.py new/vcrpy-2.0.1/tests/integration/test_aiohttp.py --- old/vcrpy-1.11.1/tests/integration/test_aiohttp.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_aiohttp.py 2018-09-19 15:58:31.000000000 +0200 @@ -1,18 +1,11 @@ +import contextlib + import pytest +asyncio = pytest.importorskip("asyncio") aiohttp = pytest.importorskip("aiohttp") -import asyncio # noqa: E402 -import contextlib # noqa: E402 - -import pytest # noqa: E402 import vcr # noqa: E402 - -from .aiohttp_utils import aiohttp_request # noqa: E402 - -try: - from .async_def import test_http # noqa: F401 -except SyntaxError: - pass +from .aiohttp_utils import aiohttp_app, aiohttp_request # noqa: E402 def run_in_loop(fn): @@ -22,19 +15,19 @@ return loop.run_until_complete(task) -def request(method, url, as_text=True, **kwargs): +def request(method, url, output='text', **kwargs): def run(loop): - return aiohttp_request(loop, method, url, as_text, **kwargs) + return aiohttp_request(loop, method, url, output=output, **kwargs) return run_in_loop(run) -def get(url, as_text=True, **kwargs): - return request('GET', url, as_text, **kwargs) +def get(url, output='text', **kwargs): + return request('GET', url, output=output, **kwargs) -def post(url, as_text=True, **kwargs): - return request('POST', url, as_text, **kwargs) +def post(url, output='text', **kwargs): + return request('POST', url, output='text', **kwargs) @pytest.fixture(params=["https", "http"]) @@ -78,15 +71,28 @@ def test_json(tmpdir, scheme): url = scheme + '://httpbin.org/get' + headers = {'Content-Type': 'application/json'} + with vcr.use_cassette(str(tmpdir.join('json.yaml'))): - _, response_json = get(url, as_text=False) + _, response_json = get(url, output='json', headers=headers) with vcr.use_cassette(str(tmpdir.join('json.yaml'))) as cassette: - _, cassette_response_json = get(url, as_text=False) + _, cassette_response_json = get(url, output='json', headers=headers) assert cassette_response_json == response_json assert cassette.play_count == 1 +def test_binary(tmpdir, scheme): + url = scheme + '://httpbin.org/image/png' + with vcr.use_cassette(str(tmpdir.join('binary.yaml'))): + _, response_binary = get(url, output='raw') + + with vcr.use_cassette(str(tmpdir.join('binary.yaml'))) as cassette: + _, cassette_response_binary = get(url, output='raw') + assert cassette_response_binary == response_binary + assert cassette.play_count == 1 + + def test_post(tmpdir, scheme): data = {'key1': 'value1', 'key2': 'value2'} url = scheme + '://httpbin.org/post' @@ -101,29 +107,73 @@ def test_params(tmpdir, scheme): url = scheme + '://httpbin.org/get' + headers = {'Content-Type': 'application/json'} params = {'a': 1, 'b': False, 'c': 'c'} + with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: - _, response_json = get(url, as_text=False, params=params) + _, response_json = get(url, output='json', params=params, headers=headers) with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: - _, cassette_response_json = get(url, as_text=False, params=params) + _, cassette_response_json = get(url, output='json', params=params, headers=headers) assert cassette_response_json == response_json assert cassette.play_count == 1 def test_params_same_url_distinct_params(tmpdir, scheme): url = scheme + '://httpbin.org/get' + headers = {'Content-Type': 'application/json'} params = {'a': 1, 'b': False, 'c': 'c'} + with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: - _, response_json = get(url, as_text=False, params=params) + _, response_json = get(url, output='json', params=params, headers=headers) with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: - _, cassette_response_json = get(url, as_text=False, params=params) + _, cassette_response_json = get(url, output='json', params=params, headers=headers) assert cassette_response_json == response_json assert cassette.play_count == 1 other_params = {'other': 'params'} with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: - response, cassette_response_text = get(url, as_text=True, params=other_params) + response, cassette_response_text = get(url, output='text', params=other_params) assert 'No match for the request' in cassette_response_text assert response.status == 599 + + +def test_params_on_url(tmpdir, scheme): + url = scheme + '://httpbin.org/get?a=1&b=foo' + headers = {'Content-Type': 'application/json'} + + with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: + _, response_json = get(url, output='json', headers=headers) + request = cassette.requests[0] + assert request.url == url + + with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: + _, cassette_response_json = get(url, output='json', headers=headers) + request = cassette.requests[0] + assert request.url == url + assert cassette_response_json == response_json + assert cassette.play_count == 1 + + +def test_aiohttp_test_client(aiohttp_client, tmpdir): + loop = asyncio.get_event_loop() + app = aiohttp_app() + url = '/' + client = loop.run_until_complete(aiohttp_client(app)) + + with vcr.use_cassette(str(tmpdir.join('get.yaml'))): + response = loop.run_until_complete(client.get(url)) + + assert response.status == 200 + response_text = loop.run_until_complete(response.text()) + assert response_text == 'hello' + + with vcr.use_cassette(str(tmpdir.join('get.yaml'))) as cassette: + response = loop.run_until_complete(client.get(url)) + + request = cassette.requests[0] + assert request.url == str(client.make_url(url)) + response_text = loop.run_until_complete(response.text()) + assert response_text == 'hello' + assert cassette.play_count == 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_httplib2.py new/vcrpy-2.0.1/tests/integration/test_httplib2.py --- old/vcrpy-1.11.1/tests/integration/test_httplib2.py 2016-05-02 02:20:30.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_httplib2.py 2018-09-19 15:58:31.000000000 +0200 @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- '''Integration tests with httplib2''' -# External imports +import sys + from six.moves.urllib_parse import urlencode import pytest import pytest_httpbin.certs -# Internal imports import vcr from assertions import assert_cassette_has_one_response @@ -19,7 +19,12 @@ Returns an httplib2 HTTP instance with the certificate replaced by the httpbin one. """ - return httplib2.Http(ca_certs=pytest_httpbin.certs.where()) + kwargs = { + 'ca_certs': pytest_httpbin.certs.where() + } + if sys.version_info[:2] == (3, 7): + kwargs['disable_ssl_certificate_validation'] = True + return httplib2.Http(**kwargs) def test_response_code(tmpdir, httpbin_both): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_ignore.py new/vcrpy-2.0.1/tests/integration/test_ignore.py --- old/vcrpy-1.11.1/tests/integration/test_ignore.py 2016-05-02 02:20:30.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_ignore.py 2018-09-18 16:52:17.000000000 +0200 @@ -26,9 +26,9 @@ with overridden_dns({'httpbin.org': '127.0.0.1'}): cass_file = str(tmpdir.join('filter_qs.yaml')) with vcr.use_cassette(cass_file, ignore_localhost=True) as cass: - urlopen('http://localhost:{0}/'.format(httpbin.port)) + urlopen('http://localhost:{}/'.format(httpbin.port)) assert len(cass) == 0 - urlopen('http://httpbin.org:{0}/'.format(httpbin.port)) + urlopen('http://httpbin.org:{}/'.format(httpbin.port)) assert len(cass) == 1 @@ -39,9 +39,9 @@ cass_file, ignore_hosts=['httpbin.org'] ) as cass: - urlopen('http://httpbin.org:{0}/'.format(httpbin.port)) + urlopen('http://httpbin.org:{}/'.format(httpbin.port)) assert len(cass) == 0 - urlopen('http://localhost:{0}/'.format(httpbin.port)) + urlopen('http://localhost:{}/'.format(httpbin.port)) assert len(cass) == 1 @@ -53,8 +53,8 @@ ignore_hosts=['httpbin.org'], ignore_localhost=True ) as cass: - urlopen('http://httpbin.org:{0}'.format(httpbin.port)) - urlopen('http://localhost:{0}'.format(httpbin.port)) + urlopen('http://httpbin.org:{}'.format(httpbin.port)) + urlopen('http://localhost:{}'.format(httpbin.port)) assert len(cass) == 0 @@ -62,12 +62,12 @@ with overridden_dns({'httpbin.org': '127.0.0.1'}): cass_file = str(tmpdir.join('filter_qs.yaml')) with vcr.use_cassette(cass_file, ignore_localhost=True) as cass: - urlopen('http://localhost:{0}'.format(httpbin.port)) + urlopen('http://localhost:{}'.format(httpbin.port)) assert len(cass) == 0 - urlopen('http://httpbin.org:{0}'.format(httpbin.port)) + urlopen('http://httpbin.org:{}'.format(httpbin.port)) assert len(cass) == 1 with vcr.use_cassette(cass_file, ignore_localhost=True) as cass: assert len(cass) == 1 - urlopen('http://localhost:{0}'.format(httpbin.port)) - urlopen('http://httpbin.org:{0}'.format(httpbin.port)) + urlopen('http://localhost:{}'.format(httpbin.port)) + urlopen('http://httpbin.org:{}'.format(httpbin.port)) assert len(cass) == 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_proxy.py new/vcrpy-2.0.1/tests/integration/test_proxy.py --- old/vcrpy-1.11.1/tests/integration/test_proxy.py 1970-01-01 01:00:00.000000000 +0100 +++ new/vcrpy-2.0.1/tests/integration/test_proxy.py 2018-09-19 15:58:31.000000000 +0200 @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +'''Test using a proxy.''' + +# External imports +import multiprocessing +import pytest + +from six.moves import socketserver, SimpleHTTPServer +from six.moves.urllib.request import urlopen + +# Internal imports +import vcr + +# Conditional imports +requests = pytest.importorskip("requests") + + +class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler): + ''' + Simple proxy server. + + (Inspired by: http://effbot.org/librarybook/simplehttpserver.htm). + ''' + def do_GET(self): + upstream_response = urlopen(self.path) + try: + status = upstream_response.status + headers = upstream_response.headers.items() + except AttributeError: + # In Python 2 the response is an addinfourl instance. + status = upstream_response.code + headers = upstream_response.info().items() + self.send_response(status, upstream_response.msg) + for header in headers: + self.send_header(*header) + self.end_headers() + self.copyfile(upstream_response, self.wfile) + + [email protected]_fixture(scope='session') +def proxy_server(): + httpd = socketserver.ThreadingTCPServer(('', 0), Proxy) + proxy_process = multiprocessing.Process( + target=httpd.serve_forever, + ) + proxy_process.start() + yield 'http://{0}:{1}'.format(*httpd.server_address) + proxy_process.terminate() + + +def test_use_proxy(tmpdir, httpbin, proxy_server): + '''Ensure that it works with a proxy.''' + with vcr.use_cassette(str(tmpdir.join('proxy.yaml'))): + response = requests.get(httpbin.url, proxies={'http': proxy_server}) + + with vcr.use_cassette(str(tmpdir.join('proxy.yaml'))) as cassette: + cassette_response = requests.get(httpbin.url, proxies={'http': proxy_server}) + + assert cassette_response.headers == response.headers + assert cassette.play_count == 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_register_persister.py new/vcrpy-2.0.1/tests/integration/test_register_persister.py --- old/vcrpy-1.11.1/tests/integration/test_register_persister.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_register_persister.py 2018-09-18 16:52:17.000000000 +0200 @@ -10,10 +10,25 @@ from vcr.persisters.filesystem import FilesystemPersister +class CustomFilesystemPersister(object): + '''Behaves just like default FilesystemPersister but adds .test extension + to the cassette file''' + @staticmethod + def load_cassette(cassette_path, serializer): + cassette_path += '.test' + return FilesystemPersister.load_cassette(cassette_path, serializer) + + @staticmethod + def save_cassette(cassette_path, cassette_dict, serializer): + cassette_path += '.test' + FilesystemPersister.save_cassette(cassette_path, cassette_dict, + serializer) + + def test_save_cassette_with_custom_persister(tmpdir, httpbin): '''Ensure you can save a cassette using custom persister''' my_vcr = vcr.VCR() - my_vcr.register_persister(FilesystemPersister) + my_vcr.register_persister(CustomFilesystemPersister) # Check to make sure directory doesnt exist assert not os.path.exists(str(tmpdir.join('nonexistent'))) @@ -23,7 +38,7 @@ urlopen(httpbin.url).read() # Callback should have made the file and the directory - assert os.path.exists(str(tmpdir.join('nonexistent', 'cassette.yml'))) + assert os.path.exists(str(tmpdir.join('nonexistent', 'cassette.yml.test'))) def test_load_cassette_with_custom_persister(tmpdir, httpbin): @@ -31,9 +46,9 @@ Ensure you can load a cassette using custom persister ''' my_vcr = vcr.VCR() - my_vcr.register_persister(FilesystemPersister) + my_vcr.register_persister(CustomFilesystemPersister) - test_fixture = str(tmpdir.join('synopsis.json')) + test_fixture = str(tmpdir.join('synopsis.json.test')) with my_vcr.use_cassette(test_fixture, serializer='json'): response = urlopen(httpbin.url).read() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_requests.py new/vcrpy-2.0.1/tests/integration/test_requests.py --- old/vcrpy-1.11.1/tests/integration/test_requests.py 2017-05-28 01:39:41.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_requests.py 2018-09-18 16:52:17.000000000 +0200 @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- '''Test requests' interaction with vcr''' +import platform import pytest +import sys import vcr from assertions import assert_cassette_empty, assert_is_json @@ -114,7 +116,10 @@ assert req1 == req2 [email protected]('sys.version_info >= (3, 6)', strict=True, raises=ConnectionError) [email protected]('sys.version_info >= (3, 6)', strict=True, raises=ConnectionError) [email protected]((3, 5) < sys.version_info < (3, 6) and + platform.python_implementation() == 'CPython', + reason='Fails on CPython 3.5') def test_post_chunked_binary_secure(tmpdir, httpbin_secure): '''Ensure that we can send chunked binary without breaking while trying to concatenate bytes with str.''' data1 = iter([b'data', b'to', b'send']) @@ -249,10 +254,8 @@ def test_post_file(tmpdir, httpbin_both): '''Ensure that we handle posting a file.''' url = httpbin_both + '/post' - with vcr.use_cassette(str(tmpdir.join('post_file.yaml'))) as cass: - # Don't use 2.7+ only style ',' separated with here because we support python 2.6 - with open('tox.ini') as f: - original_response = requests.post(url, f).content + with vcr.use_cassette(str(tmpdir.join('post_file.yaml'))) as cass, open('tox.ini') as f: + original_response = requests.post(url, f).content # This also tests that we do the right thing with matching the body when they are files. with vcr.use_cassette(str(tmpdir.join('post_file.yaml')), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_stubs.py new/vcrpy-2.0.1/tests/integration/test_stubs.py --- old/vcrpy-1.11.1/tests/integration/test_stubs.py 2016-07-16 20:58:00.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_stubs.py 2018-09-18 16:52:17.000000000 +0200 @@ -1,5 +1,6 @@ import vcr import zlib +import json import six.moves.http_client as httplib from assertions import assert_is_json @@ -83,3 +84,50 @@ assert 'content-encoding' not in inside.headers assert_is_json(inside.read()) + + +def _make_before_record_response(fields, replacement='[REDACTED]'): + def before_record_response(response): + string_body = response['body']['string'].decode('utf8') + body = json.loads(string_body) + + for field in fields: + if field in body: + body[field] = replacement + + response['body']['string'] = json.dumps(body).encode() + return response + return before_record_response + + +def test_original_response_is_not_modified_by_before_filter(tmpdir, httpbin): + testfile = str(tmpdir.join('sensitive_data_scrubbed_response.yml')) + host, port = httpbin.host, httpbin.port + field_to_scrub = 'url' + replacement = '[YOU_CANT_HAVE_THE_MANGO]' + + conn = httplib.HTTPConnection(host, port) + conn.request('GET', '/get') + outside = conn.getresponse() + + callback = _make_before_record_response([field_to_scrub], replacement) + with vcr.use_cassette(testfile, before_record_response=callback): + conn = httplib.HTTPConnection(host, port) + conn.request('GET', '/get') + inside = conn.getresponse() + + # The scrubbed field should be the same, because no cassette existed. + # Furthermore, the responses should be identical. + inside_body = json.loads(inside.read().decode('utf-8')) + outside_body = json.loads(outside.read().decode('utf-8')) + assert not inside_body[field_to_scrub] == replacement + assert inside_body[field_to_scrub] == outside_body[field_to_scrub] + + # Ensure that when a cassette exists, the scrubbed response is returned. + with vcr.use_cassette(testfile, before_record_response=callback): + conn = httplib.HTTPConnection(host, port) + conn.request('GET', '/get') + inside = conn.getresponse() + + inside_body = json.loads(inside.read().decode('utf-8')) + assert inside_body[field_to_scrub] == replacement diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_urllib2.py new/vcrpy-2.0.1/tests/integration/test_urllib2.py --- old/vcrpy-1.11.1/tests/integration/test_urllib2.py 2016-05-02 02:20:30.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_urllib2.py 2018-09-19 15:58:31.000000000 +0200 @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- '''Integration tests with urllib2''' +import ssl from six.moves.urllib.request import urlopen from six.moves.urllib_parse import urlencode import pytest_httpbin.certs @@ -12,7 +13,9 @@ def urlopen_with_cafile(*args, **kwargs): - kwargs['cafile'] = pytest_httpbin.certs.where() + context = ssl.create_default_context(cafile=pytest_httpbin.certs.where()) + context.check_hostname = False + kwargs['context'] = context try: return urlopen(*args, **kwargs) except TypeError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_urllib3.py new/vcrpy-2.0.1/tests/integration/test_urllib3.py --- old/vcrpy-1.11.1/tests/integration/test_urllib3.py 2016-05-02 02:20:30.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_urllib3.py 2018-09-18 16:52:17.000000000 +0200 @@ -5,6 +5,7 @@ import pytest import pytest_httpbin import vcr +from vcr.patch import force_reset from assertions import assert_cassette_empty, assert_is_json urllib3 = pytest.importorskip("urllib3") @@ -55,7 +56,7 @@ def test_auth(tmpdir, httpbin_both, verify_pool_mgr): '''Ensure that we can handle basic auth''' auth = ('user', 'passwd') - headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(*auth)) + headers = urllib3.util.make_headers(basic_auth='{}:{}'.format(*auth)) url = httpbin_both.url + '/basic-auth/user/passwd' with vcr.use_cassette(str(tmpdir.join('auth.yaml'))): one = verify_pool_mgr.request('GET', url, headers=headers) @@ -69,7 +70,7 @@ def test_auth_failed(tmpdir, httpbin_both, verify_pool_mgr): '''Ensure that we can save failed auth statuses''' auth = ('user', 'wrongwrongwrong') - headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(*auth)) + headers = urllib3.util.make_headers(basic_auth='{}:{}'.format(*auth)) url = httpbin_both.url + '/basic-auth/user/passwd' with vcr.use_cassette(str(tmpdir.join('auth-failed.yaml'))) as cass: # Ensure that this is empty to begin with @@ -138,3 +139,21 @@ def test_https_with_cert_validation_disabled(tmpdir, httpbin_secure, pool_mgr): with vcr.use_cassette(str(tmpdir.join('cert_validation_disabled.yaml'))): pool_mgr.request('GET', httpbin_secure.url) + + +def test_urllib3_force_reset(): + cpool = urllib3.connectionpool + http_original = cpool.HTTPConnection + https_original = cpool.HTTPSConnection + verified_https_original = cpool.VerifiedHTTPSConnection + with vcr.use_cassette(path='test'): + first_cassette_HTTPConnection = cpool.HTTPConnection + first_cassette_HTTPSConnection = cpool.HTTPSConnection + first_cassette_VerifiedHTTPSConnection = cpool.VerifiedHTTPSConnection + with force_reset(): + assert cpool.HTTPConnection is http_original + assert cpool.HTTPSConnection is https_original + assert cpool.VerifiedHTTPSConnection is verified_https_original + assert cpool.HTTPConnection is first_cassette_HTTPConnection + assert cpool.HTTPSConnection is first_cassette_HTTPSConnection + assert cpool.VerifiedHTTPSConnection is first_cassette_VerifiedHTTPSConnection diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/integration/test_wild.py new/vcrpy-2.0.1/tests/integration/test_wild.py --- old/vcrpy-1.11.1/tests/integration/test_wild.py 2016-07-03 23:47:20.000000000 +0200 +++ new/vcrpy-2.0.1/tests/integration/test_wild.py 2018-09-18 16:52:17.000000000 +0200 @@ -1,5 +1,6 @@ +import multiprocessing import pytest -from six.moves import xmlrpc_client +from six.moves import xmlrpc_client, xmlrpc_server requests = pytest.importorskip("requests") @@ -80,13 +81,27 @@ assert 'html' in r.text -def test_xmlrpclib(tmpdir): [email protected]_fixture(scope='session') +def rpc_server(): + httpd = xmlrpc_server.SimpleXMLRPCServer(('', 0)) + httpd.register_function(pow) + proxy_process = multiprocessing.Process( + target=httpd.serve_forever, + ) + try: + proxy_process.start() + yield 'http://{}:{}'.format(*httpd.server_address) + finally: + proxy_process.terminate() + + +def test_xmlrpclib(tmpdir, rpc_server): with vcr.use_cassette(str(tmpdir.join('xmlrpcvideo.yaml'))): - roundup_server = xmlrpc_client.ServerProxy('http://bugs.python.org/xmlrpc', allow_none=True) - original_schema = roundup_server.schema() + roundup_server = xmlrpc_client.ServerProxy(rpc_server, allow_none=True) + original_schema = roundup_server.pow(2, 4) 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() + roundup_server = xmlrpc_client.ServerProxy(rpc_server, allow_none=True) + second_schema = roundup_server.pow(2, 4) assert original_schema == second_schema diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/unit/test_matchers.py new/vcrpy-2.0.1/tests/unit/test_matchers.py --- old/vcrpy-1.11.1/tests/unit/test_matchers.py 2016-05-01 23:33:41.000000000 +0200 +++ new/vcrpy-2.0.1/tests/unit/test_matchers.py 2018-09-18 16:52:17.000000000 +0200 @@ -22,7 +22,7 @@ matcher = getattr(matchers, matcher_name) for k1, k2 in itertools.permutations(REQUESTS, 2): matched = matcher(REQUESTS[k1], REQUESTS[k2]) - if matcher_name in set((k1, k2)): + if matcher_name in {k1, k2}: assert not matched else: assert matched @@ -31,7 +31,7 @@ def test_uri_matcher(): for k1, k2 in itertools.permutations(REQUESTS, 2): matched = matchers.uri(REQUESTS[k1], REQUESTS[k2]) - if set((k1, k2)) != set(('base', 'method')): + if {k1, k2} != {'base', 'method'}: assert not matched else: assert matched diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tests/unit/test_vcr.py new/vcrpy-2.0.1/tests/unit/test_vcr.py --- old/vcrpy-1.11.1/tests/unit/test_vcr.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/tests/unit/test_vcr.py 2018-09-18 16:52:17.000000000 +0200 @@ -319,11 +319,11 @@ @vcr.use_cassette def function_defaults(cassette): - assert set(cassette._match_on) == set([vcr.matchers['uri']]) + assert set(cassette._match_on) == {vcr.matchers['uri']} @vcr.use_cassette(additional_matchers=('body',)) def function_additional(cassette): - assert set(cassette._match_on) == set([vcr.matchers['uri'], vcr.matchers['body']]) + assert set(cassette._match_on) == {vcr.matchers['uri'], vcr.matchers['body']} function_defaults() function_additional() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/tox.ini new/vcrpy-2.0.1/tox.ini --- old/vcrpy-1.11.1/tox.ini 2017-05-28 03:51:15.000000000 +0200 +++ new/vcrpy-2.0.1/tox.ini 2018-09-23 20:20:47.000000000 +0200 @@ -1,5 +1,5 @@ [tox] -envlist = {py26,py27,py35,py36,pypy,pypy3}-{flakes,requests216,requests213,requests27,requests26,requests25,requests24,requests23,requests22,requests1,httplib2,urllib319,urllib3110,urllib3121,tornado3,tornado4,boto,boto3,aiohttp} +envlist = {py27,py34,py35,py36,py37,pypy}-{flakes,requests27,httplib2,urllib3121,tornado4,boto3,aiohttp} [testenv:flakes] skipsdist = True @@ -13,35 +13,21 @@ commands = ./runtests.sh {posargs} deps = - # httpbin fails with latest Flask, so we pin it - Flask==0.10.1 + Flask<1 mock pytest pytest-httpbin PyYAML - requests1: requests==1.2.3 - requests216: requests==2.16.3 - requests213: requests==2.13.0 requests27: requests==2.7.0 - requests26: requests==2.6.0 - requests25: requests==2.5.0 - requests24: requests==2.4.0 - requests23: requests==2.3.0 - requests22: requests==2.2.1 httplib2: httplib2 - urllib319: urllib3==1.9.1 - urllib3110: urllib3==1.10.2 urllib3121: urllib3==1.21.1 - {py26,py27,py35,py36,pypy}-tornado3: tornado>=3,<4 - {py26,py27,py35,py36,pypy}-tornado4: tornado>=4,<5 - {py26,py27,py35,py36,pypy}-tornado3: pytest-tornado - {py26,py27,py35,py36,pypy}-tornado4: pytest-tornado - {py26,py27,py35,py36}-tornado3: pycurl - {py26,py27,py35,py36}-tornado4: pycurl - boto: boto + {py27,py35,py36,pypy}-tornado4: tornado>=4,<5 + {py27,py35,py36,pypy}-tornado4: pytest-tornado + {py27,py35,py36}-tornado4: pycurl boto3: boto3 aiohttp: aiohttp aiohttp: pytest-asyncio + aiohttp: pytest-aiohttp [flake8] max_line_length = 110 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/_handle_coroutine.py new/vcrpy-2.0.1/vcr/_handle_coroutine.py --- old/vcrpy-1.11.1/vcr/_handle_coroutine.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/_handle_coroutine.py 2018-09-19 15:58:31.000000000 +0200 @@ -1,7 +1,3 @@ -import asyncio - - [email protected] -def handle_coroutine(vcr, fn): +async def handle_coroutine(vcr, fn): # noqa: E999 with vcr as cassette: - return (yield from fn(cassette)) # noqa: E999 + return (await fn(cassette)) # noqa: E999 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/cassette.py new/vcrpy-2.0.1/vcr/cassette.py --- old/vcrpy-1.11.1/vcr/cassette.py 2017-05-27 23:28:37.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/cassette.py 2018-09-23 20:20:47.000000000 +0200 @@ -1,10 +1,12 @@ +import collections +import copy import sys import inspect import logging import wrapt -from .compat import contextlib, collections +from .compat import contextlib from .errors import UnhandledHTTPRequestError from .matchers import requests_match, uri, method from .patch import CassettePatcherBuilder @@ -14,11 +16,13 @@ try: from asyncio import iscoroutinefunction - from ._handle_coroutine import handle_coroutine except ImportError: def iscoroutinefunction(*args, **kwargs): return False +if sys.version_info[:2] >= (3, 5): + from ._handle_coroutine import handle_coroutine +else: def handle_coroutine(*args, **kwags): raise NotImplementedError('Not implemented on Python 2') @@ -134,7 +138,10 @@ except Exception: to_yield = coroutine.throw(*sys.exc_info()) else: - to_yield = coroutine.send(to_send) + try: + to_yield = coroutine.send(to_send) + except StopIteration: + break def _handle_function(self, fn): with self as cassette: @@ -174,13 +181,13 @@ def use(cls, **kwargs): return CassetteContextDecorator.from_args(cls, **kwargs) - def __init__(self, path, serializer=yamlserializer, persister=FilesystemPersister, record_mode='once', + def __init__(self, path, serializer=None, persister=None, record_mode='once', match_on=(uri, method), before_record_request=None, before_record_response=None, custom_patches=(), inject=False): - self._persister = persister + self._persister = persister or FilesystemPersister self._path = path - self._serializer = serializer + self._serializer = serializer or yamlserializer self._match_on = match_on self._before_record_request = before_record_request or (lambda x: x) self._before_record_response = before_record_response or (lambda x: x) @@ -221,6 +228,9 @@ request = self._before_record_request(request) if not request: return + # Deepcopy is here because mutation of `response` will corrupt the + # real response. + response = copy.deepcopy(response) response = self._before_record_response(response) if response is None: return @@ -303,7 +313,7 @@ pass def __str__(self): - return "<Cassette containing {0} recorded response(s)>".format( + return "<Cassette containing {} recorded response(s)>".format( len(self) ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/compat.py new/vcrpy-2.0.1/vcr/compat.py --- old/vcrpy-1.11.1/vcr/compat.py 2016-05-01 23:33:41.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/compat.py 2018-09-18 16:52:17.000000000 +0200 @@ -11,8 +11,4 @@ if not hasattr(contextlib, 'ExitStack'): import contextlib2 as contextlib -import collections -if not hasattr(collections, 'Counter'): - import backport_collections as collections - -__all__ = ['mock', 'contextlib', 'collections'] +__all__ = ['mock', 'contextlib'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/config.py new/vcrpy-2.0.1/vcr/config.py --- old/vcrpy-1.11.1/vcr/config.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/config.py 2018-09-18 16:52:17.000000000 +0200 @@ -1,4 +1,5 @@ import copy +import collections import functools import inspect import os @@ -6,7 +7,6 @@ import six -from .compat import collections from .cassette import Cassette from .serializers import yamlserializer, jsonserializer from .persisters.filesystem import FilesystemPersister @@ -78,7 +78,7 @@ serializer = self.serializers[serializer_name] except KeyError: raise KeyError( - "Serializer {0} doesn't exist or isn't registered".format( + "Serializer {} doesn't exist or isn't registered".format( serializer_name ) ) @@ -91,7 +91,7 @@ matchers.append(self.matchers[m]) except KeyError: raise KeyError( - "Matcher {0} doesn't exist or isn't registered".format(m) + "Matcher {} doesn't exist or isn't registered".format(m) ) return matchers @@ -145,6 +145,7 @@ merged_config = { 'serializer': self._get_serializer(serializer_name), + 'persister': self.persister, 'match_on': self._get_matchers( tuple(matcher_names) + tuple(additional_matchers) ), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/matchers.py new/vcrpy-2.0.1/vcr/matchers.py --- old/vcrpy-1.11.1/vcr/matchers.py 2016-10-03 00:15:12.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/matchers.py 2018-09-18 16:52:17.000000000 +0200 @@ -90,12 +90,12 @@ differences = [m for m in matches if not m[0]] if differences: log.debug( - "Requests {0} and {1} differ according to " - "the following matchers: {2}".format(r1, r2, differences) + "Requests {} and {} differ according to " + "the following matchers: {}".format(r1, r2, differences) ) def requests_match(r1, r2, matchers): matches = [(m(r1, r2), m) for m in matchers] _log_matches(r1, r2, matches) - return all([m[0] for m in matches]) + return all(m[0] for m in matches) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/migration.py new/vcrpy-2.0.1/vcr/migration.py --- old/vcrpy-1.11.1/vcr/migration.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/migration.py 2018-09-18 16:52:17.000000000 +0200 @@ -59,7 +59,7 @@ port = parts['port'] scheme = parts['protocol'] default_port = {'https': 443, 'http': 80}[scheme] - parts['port'] = ':{0}'.format(port) if port != default_port else '' + parts['port'] = ':{}'.format(port) if port != default_port else '' return "{protocol}://{host}{port}{path}".format(**parts) @@ -161,7 +161,7 @@ for file_path in files: migrated = try_migrate(file_path) status = 'OK' if migrated else 'FAIL' - sys.stderr.write("[{0}] {1}\n".format(status, file_path)) + sys.stderr.write("[{}] {}\n".format(status, file_path)) sys.stderr.write("Done.\n") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/patch.py new/vcrpy-2.0.1/vcr/patch.py --- old/vcrpy-1.11.1/vcr/patch.py 2017-05-28 03:42:53.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/patch.py 2018-09-18 16:52:17.000000000 +0200 @@ -169,7 +169,7 @@ bases = (base_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), + return type('{}{}'.format(base_class.__name__, self._cassette._path), bases, dict(cassette=self._cassette)) @_build_patchers_from_mock_triples_decorator @@ -362,8 +362,22 @@ def reset_patchers(): yield mock.patch.object(httplib, 'HTTPConnection', _HTTPConnection) yield mock.patch.object(httplib, 'HTTPSConnection', _HTTPSConnection) + try: - import requests.packages.urllib3.connectionpool as cpool + import requests + if requests.__build__ < 0x021603: + # Avoid double unmock if requests 2.16.3 + # First, this is pointless, requests.packages.urllib3 *IS* urllib3 (see packages.py) + # Second, this is unmocking twice the same classes with different namespaces + # and is creating weird issues and bugs: + # > AssertionError: assert <class 'urllib3.connection.HTTPConnection'> + # > is <class 'requests.packages.urllib3.connection.HTTPConnection'> + # This assert should work!!! + # Note that this also means that now, requests.packages is never imported + # if requests 2.16.3 or greater is used with VCRPy. + import requests.packages.urllib3.connectionpool as cpool + else: + raise ImportError("Skip requests not vendored anymore") except ImportError: # pragma: no cover pass else: @@ -386,11 +400,11 @@ pass else: yield mock.patch.object(cpool, 'VerifiedHTTPSConnection', _VerifiedHTTPSConnection) - yield mock.patch.object(cpool, 'HTTPConnection', _HTTPConnection) - yield mock.patch.object(cpool, 'HTTPSConnection', _HTTPSConnection) + yield mock.patch.object(cpool, 'HTTPConnection', _cpoolHTTPConnection) + yield mock.patch.object(cpool, 'HTTPSConnection', _cpoolHTTPSConnection) if hasattr(cpool.HTTPConnectionPool, 'ConnectionCls'): - yield mock.patch.object(cpool.HTTPConnectionPool, 'ConnectionCls', _HTTPConnection) - yield mock.patch.object(cpool.HTTPSConnectionPool, 'ConnectionCls', _HTTPSConnection) + yield mock.patch.object(cpool.HTTPConnectionPool, 'ConnectionCls', _cpoolHTTPConnection) + yield mock.patch.object(cpool.HTTPSConnectionPool, 'ConnectionCls', _cpoolHTTPSConnection) try: import botocore.vendored.requests.packages.urllib3.connectionpool as cpool diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/request.py new/vcrpy-2.0.1/vcr/request.py --- old/vcrpy-1.11.1/vcr/request.py 2016-05-01 23:33:41.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/request.py 2018-09-18 16:52:17.000000000 +0200 @@ -81,7 +81,7 @@ return self.scheme def __str__(self): - return "<Request ({0}) {1}>".format(self.method, self.uri) + return "<Request ({}) {}>".format(self.method, self.uri) def __repr__(self): return self.__str__() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/stubs/__init__.py new/vcrpy-2.0.1/vcr/stubs/__init__.py --- old/vcrpy-1.11.1/vcr/stubs/__init__.py 2017-05-28 03:40:42.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/stubs/__init__.py 2018-09-19 15:58:31.000000000 +0200 @@ -18,7 +18,7 @@ class VCRFakeSocket(object): """ A socket that doesn't do anything! - Used when playing back casssettes, when there + Used when playing back cassettes, when there is no actual open socket. """ @@ -132,10 +132,13 @@ """ port = self.real_connection.port default_port = {'https': 443, 'http': 80}[self._protocol] - return ':{0}'.format(port) if port != default_port else '' + return ':{}'.format(port) if port != default_port else '' def _uri(self, url): """Returns request absolute URI""" + if url and not url.startswith('/'): + # Then this must be a proxy request. + return url uri = "{0}://{1}{2}{3}".format( self._protocol, self.real_connection.host, @@ -146,7 +149,7 @@ def _url(self, uri): """Returns request selector url from absolute URI""" - prefix = "{0}://{1}{2}".format( + prefix = "{}://{}{}".format( self._protocol, self.real_connection.host, self._port_postfix(), @@ -161,13 +164,15 @@ body=body, headers=headers or {} ) - log.debug('Got {0}'.format(self._vcr_request)) + log.debug('Got {}'.format(self._vcr_request)) # Note: The request may not actually be finished at this point, so # I'm not sending the actual request until getresponse(). This # allows me to compare the entire length of the response to see if it # exists in the cassette. + self._sock = VCRFakeSocket() + def putrequest(self, method, url, *args, **kwargs): """ httplib gives you more than one way to do it. This is a way @@ -180,7 +185,7 @@ body="", headers={} ) - log.debug('Got {0}'.format(self._vcr_request)) + log.debug('Got {}'.format(self._vcr_request)) def putheader(self, header, *values): self._vcr_request.headers[header] = values @@ -214,7 +219,7 @@ # then return it if self.cassette.can_play_response_for(self._vcr_request): log.info( - "Playing response for {0} from cassette".format( + "Playing response for {} from cassette".format( self._vcr_request ) ) @@ -236,7 +241,7 @@ # and return it. log.info( - "{0} not in cassette, sending to real server".format( + "{} not in cassette, sending to real server".format( self._vcr_request ) ) @@ -291,11 +296,13 @@ with force_reset(): return self.real_connection.connect(*args, **kwargs) + self._sock = VCRFakeSocket() + @property def sock(self): if self.real_connection.sock: return self.real_connection.sock - return VCRFakeSocket() + return self._sock @sock.setter def sock(self, value): @@ -313,6 +320,8 @@ with force_reset(): self.real_connection = self._baseclass(*args, **kwargs) + self._sock = None + def __setattr__(self, name, value): """ We need to define this because any attributes that are set on the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/stubs/aiohttp_stubs/__init__.py new/vcrpy-2.0.1/vcr/stubs/aiohttp_stubs/__init__.py --- old/vcrpy-1.11.1/vcr/stubs/aiohttp_stubs/__init__.py 2017-05-27 21:45:01.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/stubs/aiohttp_stubs/__init__.py 2018-09-19 15:58:31.000000000 +0200 @@ -12,33 +12,46 @@ class MockClientResponse(ClientResponse): - # TODO: get encoding from header - @asyncio.coroutine - def json(self, *, encoding='utf-8', loads=json.loads): # NOQA: E999 - return loads(self.content.decode(encoding)) - - @asyncio.coroutine - def text(self, encoding='utf-8'): - return self.content.decode(encoding) + def __init__(self, method, url): + super().__init__( + method=method, + url=url, + writer=None, + continue100=None, + timer=None, + request_info=None, + traces=None, + loop=asyncio.get_event_loop(), + session=None, + ) + + async def json(self, *, encoding='utf-8', loads=json.loads, **kwargs): # NOQA: E999 + return loads(self._body.decode(encoding)) - @asyncio.coroutine - def release(self): + async def text(self, encoding='utf-8'): + return self._body.decode(encoding) + + async def read(self): + return self._body + + async def release(self): pass def vcr_request(cassette, real_request): @functools.wraps(real_request) - @asyncio.coroutine - def new_request(self, method, url, **kwargs): + async def new_request(self, method, url, **kwargs): headers = kwargs.get('headers') headers = self._prepare_headers(headers) data = kwargs.get('data') params = kwargs.get('params') + + request_url = URL(url) if params: for k, v in params.items(): params[k] = str(v) + request_url = URL(url).with_query(params) - request_url = URL(url).with_query(params) vcr_request = Request(method, str(request_url), data, headers) if cassette.can_play_response_for(vcr_request): @@ -46,9 +59,9 @@ response = MockClientResponse(method, URL(vcr_response.get('url'))) response.status = vcr_response['status']['code'] - response.content = vcr_response['body']['string'] + response._body = vcr_response['body']['string'] response.reason = vcr_response['status']['message'] - response.headers = vcr_response['headers'] + response._headers = vcr_response['headers'] response.close() return response @@ -59,11 +72,11 @@ msg = ("No match for the request {!r} was found. Can't overwrite " "existing cassette {!r} in your current record mode {!r}.") msg = msg.format(vcr_request, cassette._path, cassette.record_mode) - response.content = msg.encode() + response._body = msg.encode() response.close() return response - response = yield from real_request(self, method, url, **kwargs) # NOQA: E999 + response = await real_request(self, method, url, **kwargs) # NOQA: E999 vcr_response = { 'status': { @@ -71,7 +84,7 @@ 'message': response.reason, }, 'headers': dict(response.headers), - 'body': {'string': (yield from response.text())}, # NOQA: E999 + 'body': {'string': (await response.read())}, # NOQA: E999 'url': response.url, } cassette.append(vcr_request, vcr_response) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcr/stubs/httplib2_stubs.py new/vcrpy-2.0.1/vcr/stubs/httplib2_stubs.py --- old/vcrpy-1.11.1/vcr/stubs/httplib2_stubs.py 2016-05-02 02:20:30.000000000 +0200 +++ new/vcrpy-2.0.1/vcr/stubs/httplib2_stubs.py 2018-09-19 15:58:31.000000000 +0200 @@ -13,9 +13,7 @@ HTTPConnection.__init__.''' # Delete the keyword arguments that HTTPConnection would not recognize - safe_keys = set( - ('host', 'port', 'strict', 'timeout', 'source_address') - ) + safe_keys = {'host', 'port', 'strict', 'timeout', 'source_address'} unknown_keys = set(kwargs.keys()) - safe_keys safe_kwargs = kwargs.copy() for kw in unknown_keys: @@ -33,7 +31,7 @@ def __init__(self, *args, **kwargs): # Delete the keyword arguments that HTTPSConnection would not recognize - safe_keys = set(( + safe_keys = { 'host', 'port', 'key_file', @@ -42,7 +40,8 @@ 'timeout', 'source_address', 'ca_certs', - )) + 'disable_ssl_certificate_validation', + } unknown_keys = set(kwargs.keys()) - safe_keys safe_kwargs = kwargs.copy() for kw in unknown_keys: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcrpy.egg-info/PKG-INFO new/vcrpy-2.0.1/vcrpy.egg-info/PKG-INFO --- old/vcrpy-1.11.1/vcrpy.egg-info/PKG-INFO 2017-05-28 04:48:31.000000000 +0200 +++ new/vcrpy-2.0.1/vcrpy.egg-info/PKG-INFO 2018-09-23 20:38:58.000000000 +0200 @@ -1,12 +1,12 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: vcrpy -Version: 1.11.1 +Version: 2.0.1 Summary: Automatically mock your HTTP interactions to simplify and speed up testing Home-page: https://github.com/kevin1024/vcrpy Author: Kevin McCarthy Author-email: [email protected] License: MIT -Description: |PyPI| |Build Status| |Waffle Ready| |Gitter| +Description: |PyPI| |Python versions| |Build Status| |Waffle Ready| |Gitter| VCR.py ====== @@ -49,20 +49,6 @@ all HTTP interactions, which will update them to correspond to the new API. - Support - ------- - - VCR.py works great with the following HTTP clients: - - - requests - - aiohttp - - urllib3 - - tornado - - urllib2 - - boto - - boto3 - - License ======= @@ -70,10 +56,12 @@ more details .. |PyPI| image:: https://img.shields.io/pypi/v/vcrpy.svg - :target: https://pypi.python.org/pypi/vcrpy-unittest - .. |Build Status| image:: https://secure.travis-ci.org/kevin1024/vcrpy.png?branch=master + :target: https://pypi.python.org/pypi/vcrpy + .. |Python versions| image:: https://img.shields.io/pypi/pyversions/vcrpy.svg + :target: https://pypi.python.org/pypi/vcrpy + .. |Build Status| image:: https://secure.travis-ci.org/kevin1024/vcrpy.svg?branch=master :target: http://travis-ci.org/kevin1024/vcrpy - .. |Waffle Ready| image:: https://badge.waffle.io/kevin1024/vcrpy.png?label=ready&title=waffle + .. |Waffle Ready| image:: https://badge.waffle.io/kevin1024/vcrpy.svg?label=ready&title=waffle :target: https://waffle.io/kevin1024/vcrpy .. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg :alt: Join the chat at https://gitter.im/kevin1024/vcrpy @@ -84,7 +72,16 @@ Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Testing Classifier: Topic :: Internet :: WWW/HTTP Classifier: License :: OSI Approved :: MIT License +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcrpy.egg-info/SOURCES.txt new/vcrpy-2.0.1/vcrpy.egg-info/SOURCES.txt --- old/vcrpy-1.11.1/vcrpy.egg-info/SOURCES.txt 2017-05-28 04:48:36.000000000 +0200 +++ new/vcrpy-2.0.1/vcrpy.egg-info/SOURCES.txt 2018-09-23 20:38:58.000000000 +0200 @@ -13,7 +13,6 @@ tests/fixtures/wild/domain_redirect.yaml tests/integration/__init__.py tests/integration/aiohttp_utils.py -tests/integration/async_def.py tests/integration/test_aiohttp.py tests/integration/test_basic.py tests/integration/test_boto.py @@ -26,6 +25,7 @@ tests/integration/test_ignore.py tests/integration/test_matchers.py tests/integration/test_multiple.py +tests/integration/test_proxy.py tests/integration/test_record_mode.py tests/integration/test_register_matcher.py tests/integration/test_register_persister.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vcrpy-1.11.1/vcrpy.egg-info/requires.txt new/vcrpy-2.0.1/vcrpy.egg-info/requires.txt --- old/vcrpy-1.11.1/vcrpy.egg-info/requires.txt 2017-05-28 04:48:31.000000000 +0200 +++ new/vcrpy-2.0.1/vcrpy.egg-info/requires.txt 2018-09-23 20:38:58.000000000 +0200 @@ -1,16 +1,10 @@ PyYAML wrapt six>=1.5 -yarl - -[:python_version in "2.4, 2.5, 2.6"] -contextlib2 -backport_collections -mock -[:python_version in "2.7, 3.1, 3.2"] +[:python_version == "2.7"] contextlib2 mock -[:python_version in "3.4, 3.5, 3.6"] +[:python_version >= "3.4"] yarl
