Skip to content

Commit 4b3735c

Browse files
committed
Drop support to python 3.7
1 parent c41bd2b commit 4b3735c

29 files changed

+68
-106
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
fail-fast: false
1515
matrix:
16-
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.8"]
16+
python-version: ["3.8", "3.9", "3.10", "3.11", "pypy-3.8"]
1717

1818
steps:
1919
- uses: actions/checkout@v3.5.2

docs/contributing.rst

+6-6
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,11 @@ The test suite is pretty big and slow, but you can tell tox to only run specific
9696

9797
tox -e {pyNN}-{HTTP_LIBRARY} -- <pytest flags passed through>
9898

99-
tox -e py37-requests -- -v -k "'test_status_code or test_gzip'"
100-
tox -e py37-requests -- -v --last-failed
99+
tox -e py38-requests -- -v -k "'test_status_code or test_gzip'"
100+
tox -e py38-requests -- -v --last-failed
101101

102102
This will run only tests that look like ``test_status_code`` or
103-
``test_gzip`` in the test suite, and only in the python 3.7 environment
103+
``test_gzip`` in the test suite, and only in the python 3.8 environment
104104
that has ``requests`` installed.
105105

106106
Also, in order for the boto tests to run, you will need an AWS key.
@@ -130,17 +130,17 @@ in this example::
130130
pip install tox tox-pyenv
131131

132132
# Install supported versions (at time of writing), this does not activate them
133-
pyenv install 3.7.5 3.8.0 pypy3.8
133+
pyenv install 3.8.0 pypy3.8
134134

135135
# This activates them
136-
pyenv local 3.7.5 3.8.0 pypy3.8
136+
pyenv local 3.8.0 pypy3.8
137137

138138
# Run the whole test suite
139139
tox
140140

141141
# Run the whole test suite or just part of it
142142
tox -e lint
143-
tox -e py37-requests
143+
tox -e py38-requests
144144

145145

146146
Troubleshooting on MacOSX

docs/installation.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ with pip::
99
Compatibility
1010
-------------
1111

12-
VCR.py supports Python 3.7+, and `pypy <http://pypy.org>`__.
12+
VCR.py supports Python 3.8+, and `pypy <http://pypy.org>`__.
1313

1414
The following HTTP libraries are supported:
1515

setup.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ def run_tests(self):
4545
install_requires = [
4646
"PyYAML",
4747
"wrapt",
48-
"six>=1.5",
4948
"yarl",
5049
]
5150

@@ -59,7 +58,7 @@ def run_tests(self):
5958
author_email="me@kevinmccarthy.org",
6059
url="https://github.com/kevin1024/vcrpy",
6160
packages=find_packages(exclude=["tests*"]),
62-
python_requires=">=3.7",
61+
python_requires=">=3.8",
6362
install_requires=install_requires,
6463
license="MIT",
6564
tests_require=["pytest", "mock", "pytest-httpbin"],
@@ -69,7 +68,6 @@ def run_tests(self):
6968
"Intended Audience :: Developers",
7069
"Programming Language :: Python",
7170
"Programming Language :: Python :: 3",
72-
"Programming Language :: Python :: 3.7",
7371
"Programming Language :: Python :: 3.8",
7472
"Programming Language :: Python :: 3.9",
7573
"Programming Language :: Python :: 3.10",

tests/integration/test_aiohttp.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def test_post(tmpdir, body, caplog, mockbin_request_url):
143143
(
144144
log
145145
for log in caplog.records
146-
if log.getMessage() == "<Request (POST) {}> not in cassette, sending to real server".format(url)
146+
if log.getMessage() == f"<Request (POST) {url}> not in cassette, sending to real server"
147147
),
148148
None,
149149
), "Log message not found."

tests/integration/test_basic.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Basic tests for cassettes"""
32

43
# External imports

tests/integration/test_boto3.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
# https://github.com/boto/botocore/pull/1495
2121
boto3_skip_vendored_requests = pytest.mark.skipif(
2222
botocore_awsrequest,
23-
reason="botocore version {ver} does not use vendored requests anymore.".format(ver=botocore.__version__),
23+
reason=f"botocore version {botocore.__version__} does not use vendored requests anymore.",
2424
)
2525

2626
boto3_skip_awsrequest = pytest.mark.skipif(
2727
not botocore_awsrequest,
28-
reason="botocore version {ver} still uses vendored requests.".format(ver=botocore.__version__),
28+
reason=f"botocore version {botocore.__version__} still uses vendored requests.",
2929
)
3030

3131
IAM_USER_NAME = "vcrpy"

tests/integration/test_disksaver.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Basic tests about save behavior"""
32

43
# External imports

tests/integration/test_httplib2.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Integration tests with httplib2"""
32
from urllib.parse import urlencode
43

tests/integration/test_ignore.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -28,41 +28,41 @@ def test_ignore_localhost(tmpdir, httpbin):
2828
with overridden_dns({"httpbin.org": "127.0.0.1"}):
2929
cass_file = str(tmpdir.join("filter_qs.yaml"))
3030
with vcr.use_cassette(cass_file, ignore_localhost=True) as cass:
31-
urlopen("http://localhost:{}/".format(httpbin.port))
31+
urlopen(f"http://localhost:{httpbin.port}/")
3232
assert len(cass) == 0
33-
urlopen("http://httpbin.org:{}/".format(httpbin.port))
33+
urlopen(f"http://httpbin.org:{httpbin.port}/")
3434
assert len(cass) == 1
3535

3636

3737
def test_ignore_httpbin(tmpdir, httpbin):
3838
with overridden_dns({"httpbin.org": "127.0.0.1"}):
3939
cass_file = str(tmpdir.join("filter_qs.yaml"))
4040
with vcr.use_cassette(cass_file, ignore_hosts=["httpbin.org"]) as cass:
41-
urlopen("http://httpbin.org:{}/".format(httpbin.port))
41+
urlopen(f"http://httpbin.org:{httpbin.port}/")
4242
assert len(cass) == 0
43-
urlopen("http://localhost:{}/".format(httpbin.port))
43+
urlopen(f"http://localhost:{httpbin.port}/")
4444
assert len(cass) == 1
4545

4646

4747
def test_ignore_localhost_and_httpbin(tmpdir, httpbin):
4848
with overridden_dns({"httpbin.org": "127.0.0.1"}):
4949
cass_file = str(tmpdir.join("filter_qs.yaml"))
5050
with vcr.use_cassette(cass_file, ignore_hosts=["httpbin.org"], ignore_localhost=True) as cass:
51-
urlopen("http://httpbin.org:{}".format(httpbin.port))
52-
urlopen("http://localhost:{}".format(httpbin.port))
51+
urlopen(f"http://httpbin.org:{httpbin.port}")
52+
urlopen(f"http://localhost:{httpbin.port}")
5353
assert len(cass) == 0
5454

5555

5656
def test_ignore_localhost_twice(tmpdir, httpbin):
5757
with overridden_dns({"httpbin.org": "127.0.0.1"}):
5858
cass_file = str(tmpdir.join("filter_qs.yaml"))
5959
with vcr.use_cassette(cass_file, ignore_localhost=True) as cass:
60-
urlopen("http://localhost:{}".format(httpbin.port))
60+
urlopen(f"http://localhost:{httpbin.port}")
6161
assert len(cass) == 0
62-
urlopen("http://httpbin.org:{}".format(httpbin.port))
62+
urlopen(f"http://httpbin.org:{httpbin.port}")
6363
assert len(cass) == 1
6464
with vcr.use_cassette(cass_file, ignore_localhost=True) as cass:
6565
assert len(cass) == 1
66-
urlopen("http://localhost:{}".format(httpbin.port))
67-
urlopen("http://httpbin.org:{}".format(httpbin.port))
66+
urlopen(f"http://localhost:{httpbin.port}")
67+
urlopen(f"http://httpbin.org:{httpbin.port}")
6868
assert len(cass) == 1

tests/integration/test_proxy.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Test using a proxy."""
32

43
import http.server

tests/integration/test_register_persister.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Tests for cassettes with custom persistence"""
32

43
# External imports
@@ -10,7 +9,7 @@
109
from vcr.persisters.filesystem import FilesystemPersister
1110

1211

13-
class CustomFilesystemPersister(object):
12+
class CustomFilesystemPersister:
1413
"""Behaves just like default FilesystemPersister but adds .test extension
1514
to the cassette file"""
1615

tests/integration/test_requests.py

-16
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,6 @@ def test_post_chunked_binary(tmpdir, httpbin):
114114
assert req1 == req2
115115

116116

117-
@pytest.mark.skipif("sys.version_info >= (3, 6)", strict=True, raises=ConnectionError)
118-
def test_post_chunked_binary_secure(tmpdir, httpbin_secure):
119-
"""Ensure that we can send chunked binary without breaking while trying to concatenate bytes with str."""
120-
data1 = iter([b"data", b"to", b"send"])
121-
data2 = iter([b"data", b"to", b"send"])
122-
url = httpbin_secure.url + "/post"
123-
with vcr.use_cassette(str(tmpdir.join("requests.yaml"))):
124-
req1 = requests.post(url, data1).content
125-
print(req1)
126-
127-
with vcr.use_cassette(str(tmpdir.join("requests.yaml"))):
128-
req2 = requests.post(url, data2).content
129-
130-
assert req1 == req2
131-
132-
133117
def test_redirects(tmpdir, httpbin_both):
134118
"""Ensure that we can handle redirects"""
135119
url = httpbin_both + "/redirect-to?url=bytes/1024"

tests/integration/test_tornado.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Test requests' interaction with vcr"""
32

43
import json

tests/integration/test_urllib2.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Integration tests with urllib2"""
32

43
import ssl

tests/unit/test_migration.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ def test_try_migrate_with_json(tmpdir):
1717
cassette = tmpdir.join("cassette.json").strpath
1818
shutil.copy("tests/fixtures/migration/old_cassette.json", cassette)
1919
assert vcr.migration.try_migrate(cassette)
20-
with open("tests/fixtures/migration/new_cassette.json", "r") as f:
20+
with open("tests/fixtures/migration/new_cassette.json") as f:
2121
expected_json = json.load(f)
22-
with open(cassette, "r") as f:
22+
with open(cassette) as f:
2323
actual_json = json.load(f)
2424
assert actual_json == expected_json
2525

@@ -28,9 +28,9 @@ def test_try_migrate_with_yaml(tmpdir):
2828
cassette = tmpdir.join("cassette.yaml").strpath
2929
shutil.copy("tests/fixtures/migration/old_cassette.yaml", cassette)
3030
assert vcr.migration.try_migrate(cassette)
31-
with open("tests/fixtures/migration/new_cassette.yaml", "r") as f:
31+
with open("tests/fixtures/migration/new_cassette.yaml") as f:
3232
expected_yaml = yaml.load(f, Loader=Loader)
33-
with open(cassette, "r") as f:
33+
with open(cassette) as f:
3434
actual_yaml = yaml.load(f, Loader=Loader)
3535
assert actual_yaml == expected_yaml
3636

tests/unit/test_response.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# coding: UTF-8
21
import io
32

43
from vcr.stubs import VCRHTTPResponse

tests/unit/test_serialize.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- encoding: utf-8 -*-
21
from unittest import mock
32

43
import pytest
@@ -9,24 +8,24 @@
98

109

1110
def test_deserialize_old_yaml_cassette():
12-
with open("tests/fixtures/migration/old_cassette.yaml", "r") as f:
11+
with open("tests/fixtures/migration/old_cassette.yaml") as f:
1312
with pytest.raises(ValueError):
1413
deserialize(f.read(), yamlserializer)
1514

1615

1716
def test_deserialize_old_json_cassette():
18-
with open("tests/fixtures/migration/old_cassette.json", "r") as f:
17+
with open("tests/fixtures/migration/old_cassette.json") as f:
1918
with pytest.raises(ValueError):
2019
deserialize(f.read(), jsonserializer)
2120

2221

2322
def test_deserialize_new_yaml_cassette():
24-
with open("tests/fixtures/migration/new_cassette.yaml", "r") as f:
23+
with open("tests/fixtures/migration/new_cassette.yaml") as f:
2524
deserialize(f.read(), yamlserializer)
2625

2726

2827
def test_deserialize_new_json_cassette():
29-
with open("tests/fixtures/migration/new_cassette.json", "r") as f:
28+
with open("tests/fixtures/migration/new_cassette.json") as f:
3029
deserialize(f.read(), jsonserializer)
3130

3231

tests/unit/test_vcr.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ def function_with_return():
335335
assert ret == function_with_return()
336336

337337

338-
class TestVCRClass(VCR().test_case()):
338+
class TestVCRClass(VCR()):
339339
def no_decoration(self):
340340
assert httplib.HTTPConnection == _HTTPConnection
341341
self.test_dynamically_added()

tox.ini

+8-10
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ skip_missing_interpreters=true
33
envlist =
44
cov-clean,
55
lint,
6-
{py37,py38,py39,py310,py311}-{requests,httplib2,urllib3,tornado4,boto3,aiohttp,httpx},
6+
{py38,py39,py310,py311}-{requests,httplib2,urllib3,tornado4,boto3,aiohttp,httpx},
77
{pypy3}-{requests,httplib2,urllib3,tornado4,boto3},
88
{py310}-httpx019,
99
cov-report
1010

1111

1212
[gh-actions]
1313
python =
14-
3.7: py37
1514
3.8: py38
1615
3.9: py39
1716
3.10: py310, lint
@@ -65,9 +64,9 @@ deps =
6564
# In other circumstances, we might want to generate a PDF or an ebook
6665
commands =
6766
sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
68-
# We use Python 3.7. Tox sometimes tries to autodetect it based on the name of
67+
# We use Python 3.8. Tox sometimes tries to autodetect it based on the name of
6968
# the testenv, but "docs" does not give useful clues so we have to be explicit.
70-
basepython = python3.7
69+
basepython = python3.8
7170

7271
[testenv]
7372
# Need to use develop install so that paths
@@ -94,15 +93,14 @@ deps =
9493
aiohttp: pytest-asyncio
9594
aiohttp: pytest-aiohttp
9695
httpx: httpx
97-
{py37,py38,py39,py310}-{httpx}: httpx
98-
{py37,py38,py39,py310}-{httpx}: pytest-asyncio
96+
{py38,py39,py310}-{httpx}: httpx
97+
{py38,py39,py310}-{httpx}: pytest-asyncio
9998
httpx: httpx>0.19
100-
# httpx==0.19 is the latest version that supports allow_redirects, newer versions use follow_redirects
10199
httpx019: httpx==0.19
102-
{py37,py38,py39,py310}-{httpx}: pytest-asyncio
100+
{py38,py39,py310}-{httpx}: pytest-asyncio
103101
depends =
104-
lint,{py37,py38,py39,py310,py311,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py37,py38,py39,py310,py311}-{aiohttp},{py37,py38,py39,py310,py311}-{httpx}: cov-clean
105-
cov-report: lint,{py37,py38,py39,py310,py311,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py37,py38,py39,py310,py311}-{aiohttp}
102+
lint,{py38,py39,py310,py311,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py38,py39,py310,py311}-{aiohttp},{py38,py39,py310,py311}-{httpx}: cov-clean
103+
cov-report: lint,{py38,py39,py310,py311,pypy3}-{requests,httplib2,urllib3,tornado4,boto3},{py38,py39,py310,py311}-{aiohttp}
106104
passenv =
107105
AWS_ACCESS_KEY_ID
108106
AWS_DEFAULT_REGION

vcr/cassette.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ def play_response(self, request):
280280
return response
281281
# The cassette doesn't contain the request asked for.
282282
raise UnhandledHTTPRequestError(
283-
"The cassette (%r) doesn't contain the request (%r) asked for" % (self._path, request)
283+
f"The cassette ({self._path!r}) doesn't contain the request ({request!r}) asked for"
284284
)
285285

286286
def responses_of(self, request):
@@ -295,7 +295,7 @@ def responses_of(self, request):
295295
return responses
296296
# The cassette doesn't contain the request asked for.
297297
raise UnhandledHTTPRequestError(
298-
"The cassette (%r) doesn't contain the request (%r) asked for" % (self._path, request)
298+
f"The cassette ({self._path!r}) doesn't contain the request ({request!r}) asked for"
299299
)
300300

301301
def rewind(self):
@@ -356,7 +356,7 @@ def _load(self):
356356
pass
357357

358358
def __str__(self):
359-
return "<Cassette containing {} recorded response(s)>".format(len(self))
359+
return f"<Cassette containing {len(self)} recorded response(s)>"
360360

361361
def __len__(self):
362362
"""Return the number of request,response pairs stored in here"""

0 commit comments

Comments
 (0)