Skip to content

Commit

Permalink
Drop support to python 3.7
Browse files Browse the repository at this point in the history
  • Loading branch information
jairhenrique committed Jun 9, 2023
1 parent f4316d2 commit 3e46616
Show file tree
Hide file tree
Showing 31 changed files with 69 additions and 132 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.8"]
python-version: ["3.8", "3.9", "3.10", "3.11", "pypy-3.8"]

steps:
- uses: actions/checkout@v3.5.2
Expand Down
1 change: 0 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# vcrpy documentation build configuration file, created by
# sphinx-quickstart on Sun Sep 13 11:18:00 2015.
Expand Down
12 changes: 6 additions & 6 deletions docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ The test suite is pretty big and slow, but you can tell tox to only run specific

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

tox -e py37-requests -- -v -k "'test_status_code or test_gzip'"
tox -e py37-requests -- -v --last-failed
tox -e py38-requests -- -v -k "'test_status_code or test_gzip'"
tox -e py38-requests -- -v --last-failed

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

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

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

# This activates them
pyenv local 3.7.5 3.8.0 pypy3.8
pyenv local 3.8.0 pypy3.8

# Run the whole test suite
tox

# Run the whole test suite or just part of it
tox -e lint
tox -e py37-requests
tox -e py38-requests


Troubleshooting on MacOSX
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ with pip::
Compatibility
-------------

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

The following HTTP libraries are supported:

Expand Down
6 changes: 2 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from setuptools import find_packages, setup
from setuptools.command.test import test as TestCommand

long_description = open("README.rst", "r").read()
long_description = open("README.rst").read()
here = os.path.abspath(os.path.dirname(__file__))


Expand Down Expand Up @@ -45,7 +45,6 @@ def run_tests(self):
install_requires = [
"PyYAML",
"wrapt",
"six>=1.5",
"yarl",
# Support for urllib3 >=2 needs Python >=3.10
# so we need to block urllib3 >=2 for Python <3.10 for now.
Expand Down Expand Up @@ -85,7 +84,7 @@ def run_tests(self):
author_email="me@kevinmccarthy.org",
url="https://github.com/kevin1024/vcrpy",
packages=find_packages(exclude=["tests*"]),
python_requires=">=3.7",
python_requires=">=3.8",
install_requires=install_requires,
license="MIT",
tests_require=tests_require,
Expand All @@ -95,7 +94,6 @@ def run_tests(self):
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def test_post(tmpdir, body, caplog, mockbin_request_url):
(
log
for log in caplog.records
if log.getMessage() == "<Request (POST) {}> not in cassette, sending to real server".format(url)
if log.getMessage() == f"<Request (POST) {url}> not in cassette, sending to real server"
),
None,
), "Log message not found."
Expand Down
1 change: 0 additions & 1 deletion tests/integration/test_basic.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Basic tests for cassettes"""

# External imports
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_boto3.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
# https://github.com/boto/botocore/pull/1495
boto3_skip_vendored_requests = pytest.mark.skipif(
botocore_awsrequest,
reason="botocore version {ver} does not use vendored requests anymore.".format(ver=botocore.__version__),
reason=f"botocore version {botocore.__version__} does not use vendored requests anymore.",
)

boto3_skip_awsrequest = pytest.mark.skipif(
not botocore_awsrequest,
reason="botocore version {ver} still uses vendored requests.".format(ver=botocore.__version__),
reason=f"botocore version {botocore.__version__} still uses vendored requests.",
)

IAM_USER_NAME = "vcrpy"
Expand Down
1 change: 0 additions & 1 deletion tests/integration/test_disksaver.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Basic tests about save behavior"""

# External imports
Expand Down
1 change: 0 additions & 1 deletion tests/integration/test_httplib2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Integration tests with httplib2"""
from urllib.parse import urlencode

Expand Down
20 changes: 10 additions & 10 deletions tests/integration/test_ignore.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,41 @@ def test_ignore_localhost(tmpdir, httpbin):
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:{}/".format(httpbin.port))
urlopen(f"http://localhost:{httpbin.port}/")
assert len(cass) == 0
urlopen("http://httpbin.org:{}/".format(httpbin.port))
urlopen(f"http://httpbin.org:{httpbin.port}/")
assert len(cass) == 1


def test_ignore_httpbin(tmpdir, httpbin):
with overridden_dns({"httpbin.org": "127.0.0.1"}):
cass_file = str(tmpdir.join("filter_qs.yaml"))
with vcr.use_cassette(cass_file, ignore_hosts=["httpbin.org"]) as cass:
urlopen("http://httpbin.org:{}/".format(httpbin.port))
urlopen(f"http://httpbin.org:{httpbin.port}/")
assert len(cass) == 0
urlopen("http://localhost:{}/".format(httpbin.port))
urlopen(f"http://localhost:{httpbin.port}/")
assert len(cass) == 1


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


def test_ignore_localhost_twice(tmpdir, httpbin):
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:{}".format(httpbin.port))
urlopen(f"http://localhost:{httpbin.port}")
assert len(cass) == 0
urlopen("http://httpbin.org:{}".format(httpbin.port))
urlopen(f"http://httpbin.org:{httpbin.port}")
assert len(cass) == 1
with vcr.use_cassette(cass_file, ignore_localhost=True) as cass:
assert len(cass) == 1
urlopen("http://localhost:{}".format(httpbin.port))
urlopen("http://httpbin.org:{}".format(httpbin.port))
urlopen(f"http://localhost:{httpbin.port}")
urlopen(f"http://httpbin.org:{httpbin.port}")
assert len(cass) == 1
1 change: 0 additions & 1 deletion tests/integration/test_proxy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Test using a proxy."""

import http.server
Expand Down
1 change: 0 additions & 1 deletion tests/integration/test_register_persister.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Tests for cassettes with custom persistence"""

# External imports
Expand Down
16 changes: 0 additions & 16 deletions tests/integration/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,6 @@ def test_post_chunked_binary(tmpdir, httpbin):
assert req1 == req2


@pytest.mark.skipif("sys.version_info >= (3, 6)", strict=True, raises=ConnectionError)
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"])
data2 = iter([b"data", b"to", b"send"])
url = httpbin_secure.url + "/post"
with vcr.use_cassette(str(tmpdir.join("requests.yaml"))):
req1 = requests.post(url, data1).content
print(req1)

with vcr.use_cassette(str(tmpdir.join("requests.yaml"))):
req2 = requests.post(url, data2).content

assert req1 == req2


def test_redirects(tmpdir, httpbin_both):
"""Ensure that we can handle redirects"""
url = httpbin_both + "/redirect-to?url=bytes/1024"
Expand Down
1 change: 0 additions & 1 deletion tests/integration/test_tornado.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Test requests' interaction with vcr"""

import json
Expand Down
1 change: 0 additions & 1 deletion tests/integration/test_urllib2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Integration tests with urllib2"""

import ssl
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/test_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ def test_try_migrate_with_json(tmpdir):
cassette = tmpdir.join("cassette.json").strpath
shutil.copy("tests/fixtures/migration/old_cassette.json", cassette)
assert vcr.migration.try_migrate(cassette)
with open("tests/fixtures/migration/new_cassette.json", "r") as f:
with open("tests/fixtures/migration/new_cassette.json") as f:
expected_json = json.load(f)
with open(cassette, "r") as f:
with open(cassette) as f:
actual_json = json.load(f)
assert actual_json == expected_json

Expand All @@ -28,9 +28,9 @@ def test_try_migrate_with_yaml(tmpdir):
cassette = tmpdir.join("cassette.yaml").strpath
shutil.copy("tests/fixtures/migration/old_cassette.yaml", cassette)
assert vcr.migration.try_migrate(cassette)
with open("tests/fixtures/migration/new_cassette.yaml", "r") as f:
with open("tests/fixtures/migration/new_cassette.yaml") as f:
expected_yaml = yaml.load(f, Loader=Loader)
with open(cassette, "r") as f:
with open(cassette) as f:
actual_yaml = yaml.load(f, Loader=Loader)
assert actual_yaml == expected_yaml

Expand Down
1 change: 0 additions & 1 deletion tests/unit/test_response.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# coding: UTF-8
import io

from vcr.stubs import VCRHTTPResponse
Expand Down
9 changes: 4 additions & 5 deletions tests/unit/test_serialize.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- encoding: utf-8 -*-
from unittest import mock

import pytest
Expand All @@ -9,24 +8,24 @@


def test_deserialize_old_yaml_cassette():
with open("tests/fixtures/migration/old_cassette.yaml", "r") as f:
with open("tests/fixtures/migration/old_cassette.yaml") as f:
with pytest.raises(ValueError):
deserialize(f.read(), yamlserializer)


def test_deserialize_old_json_cassette():
with open("tests/fixtures/migration/old_cassette.json", "r") as f:
with open("tests/fixtures/migration/old_cassette.json") as f:
with pytest.raises(ValueError):
deserialize(f.read(), jsonserializer)


def test_deserialize_new_yaml_cassette():
with open("tests/fixtures/migration/new_cassette.yaml", "r") as f:
with open("tests/fixtures/migration/new_cassette.yaml") as f:
deserialize(f.read(), yamlserializer)


def test_deserialize_new_json_cassette():
with open("tests/fixtures/migration/new_cassette.json", "r") as f:
with open("tests/fixtures/migration/new_cassette.json") as f:
deserialize(f.read(), jsonserializer)


Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_vcr.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def function_with_return():
assert ret == function_with_return()


class TestVCRClass(VCR().test_case()):
class TestVCRClass(VCR()):
def no_decoration(self):
assert httplib.HTTPConnection == _HTTPConnection
self.test_dynamically_added()
Expand Down
18 changes: 8 additions & 10 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ skip_missing_interpreters=true
envlist =
cov-clean,
lint,
{py37,py38,py39,py310,py311}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3,aiohttp,httpx},
{py38,py39,py310,py311}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3,aiohttp,httpx},
{py310,py311}-{requests-urllib3-2,urllib3-2},
{pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},
{py310}-httpx019,
Expand All @@ -12,7 +12,6 @@ envlist =

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

[testenv]
# Need to use develop install so that paths
Expand All @@ -94,15 +93,14 @@ deps =
aiohttp: pytest-asyncio
aiohttp: pytest-aiohttp
httpx: httpx
{py37,py38,py39,py310}-{httpx}: httpx
{py37,py38,py39,py310}-{httpx}: pytest-asyncio
{py38,py39,py310}-{httpx}: httpx
{py38,py39,py310}-{httpx}: pytest-asyncio
httpx: httpx>0.19
# httpx==0.19 is the latest version that supports allow_redirects, newer versions use follow_redirects
httpx019: httpx==0.19
{py37,py38,py39,py310}-{httpx}: pytest-asyncio
{py38,py39,py310}-{httpx}: pytest-asyncio
depends =
lint,{py37,py38,py39,py310,py311,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311}-{requests-urllib3-2,urllib3-2},{py37,py38,py39,py310,py311}-{aiohttp},{py37,py38,py39,py310,py311}-{httpx}: cov-clean
cov-report: lint,{py37,py38,py39,py310,py311,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311}-{requests-urllib3-2,urllib3-2},{py37,py38,py39,py310,py311}-{aiohttp}
lint,{py38,py39,py310,py311,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311}-{requests-urllib3-2,urllib3-2},{py38,py39,py310,py311}-{aiohttp},{py38,py39,py310,py311}-{httpx}: cov-clean
cov-report: lint,{py38,py39,py310,py311,pypy3}-{requests-urllib3-1,httplib2,urllib3-1,tornado4,boto3},{py310,py311}-{requests-urllib3-2,urllib3-2},{py38,py39,py310,py311}-{aiohttp}
passenv =
AWS_ACCESS_KEY_ID
AWS_DEFAULT_REGION
Expand Down
6 changes: 3 additions & 3 deletions vcr/cassette.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def play_response(self, request):
return response
# The cassette doesn't contain the request asked for.
raise UnhandledHTTPRequestError(
"The cassette (%r) doesn't contain the request (%r) asked for" % (self._path, request)
f"The cassette ({self._path!r}) doesn't contain the request ({request!r}) asked for"
)

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

def rewind(self):
Expand Down Expand Up @@ -356,7 +356,7 @@ def _load(self):
pass

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

def __len__(self):
"""Return the number of request,response pairs stored in here"""
Expand Down
Loading

0 comments on commit 3e46616

Please sign in to comment.