From 7373caf32288c98c78ba4511e6342e2f13b9b833 Mon Sep 17 00:00:00 2001 From: Jair Henrique Date: Wed, 10 May 2023 18:21:29 -0300 Subject: [PATCH] Drop support to python 3.7 --- .github/workflows/main.yml | 2 +- docs/conf.py | 1 - docs/contributing.rst | 12 ++++++------ docs/installation.rst | 2 +- setup.py | 6 ++---- tests/integration/test_aiohttp.py | 2 +- tests/integration/test_basic.py | 1 - tests/integration/test_boto3.py | 4 ++-- tests/integration/test_disksaver.py | 1 - tests/integration/test_httplib2.py | 1 - tests/integration/test_ignore.py | 20 ++++++++++---------- tests/integration/test_proxy.py | 1 - tests/integration/test_register_persister.py | 1 - tests/integration/test_requests.py | 16 ---------------- tests/integration/test_tornado.py | 1 - tests/integration/test_urllib2.py | 1 - tests/unit/test_migration.py | 8 ++++---- tests/unit/test_response.py | 1 - tests/unit/test_serialize.py | 9 ++++----- tox.ini | 18 ++++++++---------- vcr/cassette.py | 6 +++--- vcr/config.py | 9 +++------ vcr/matchers.py | 16 ++++++++-------- vcr/migration.py | 6 +++--- vcr/patch.py | 4 +--- vcr/request.py | 2 +- vcr/stubs/__init__.py | 14 +++++++------- vcr/stubs/aiohttp_stubs.py | 2 +- vcr/unittest.py | 2 +- vcr/util.py | 6 +----- 30 files changed, 68 insertions(+), 107 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 54b1ef75..80ddbfb3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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 diff --git a/docs/conf.py b/docs/conf.py index a3ffd5e6..b410b01e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # vcrpy documentation build configuration file, created by # sphinx-quickstart on Sun Sep 13 11:18:00 2015. diff --git a/docs/contributing.rst b/docs/contributing.rst index d41a23b6..f55134ff 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -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} -- - 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. @@ -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 diff --git a/docs/installation.rst b/docs/installation.rst index a6a0789c..a9f9ffb3 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -9,7 +9,7 @@ with pip:: Compatibility ------------- -VCR.py supports Python 3.7+, and `pypy `__. +VCR.py supports Python 3.8+, and `pypy `__. The following HTTP libraries are supported: diff --git a/setup.py b/setup.py index 7c829265..49d7ddcb 100644 --- a/setup.py +++ b/setup.py @@ -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__)) @@ -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. @@ -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, @@ -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", diff --git a/tests/integration/test_aiohttp.py b/tests/integration/test_aiohttp.py index 33bac5c6..ba2d6269 100644 --- a/tests/integration/test_aiohttp.py +++ b/tests/integration/test_aiohttp.py @@ -143,7 +143,7 @@ def test_post(tmpdir, body, caplog, mockbin_request_url): ( log for log in caplog.records - if log.getMessage() == " not in cassette, sending to real server".format(url) + if log.getMessage() == f" not in cassette, sending to real server" ), None, ), "Log message not found." diff --git a/tests/integration/test_basic.py b/tests/integration/test_basic.py index 063e2819..fba9fe22 100644 --- a/tests/integration/test_basic.py +++ b/tests/integration/test_basic.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Basic tests for cassettes""" # External imports diff --git a/tests/integration/test_boto3.py b/tests/integration/test_boto3.py index 0bdb6a01..5c2904ae 100644 --- a/tests/integration/test_boto3.py +++ b/tests/integration/test_boto3.py @@ -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" diff --git a/tests/integration/test_disksaver.py b/tests/integration/test_disksaver.py index f72b57d7..2529c7ee 100644 --- a/tests/integration/test_disksaver.py +++ b/tests/integration/test_disksaver.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Basic tests about save behavior""" # External imports diff --git a/tests/integration/test_httplib2.py b/tests/integration/test_httplib2.py index 2d5ac09e..7aa6cbca 100644 --- a/tests/integration/test_httplib2.py +++ b/tests/integration/test_httplib2.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Integration tests with httplib2""" from urllib.parse import urlencode diff --git a/tests/integration/test_ignore.py b/tests/integration/test_ignore.py index 2dd8118f..aec0d40c 100644 --- a/tests/integration/test_ignore.py +++ b/tests/integration/test_ignore.py @@ -28,9 +28,9 @@ 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 @@ -38,9 +38,9 @@ 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 @@ -48,8 +48,8 @@ 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 @@ -57,12 +57,12 @@ 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 diff --git a/tests/integration/test_proxy.py b/tests/integration/test_proxy.py index 6eb62239..e4376432 100644 --- a/tests/integration/test_proxy.py +++ b/tests/integration/test_proxy.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Test using a proxy.""" import http.server diff --git a/tests/integration/test_register_persister.py b/tests/integration/test_register_persister.py index 1391b981..1d6fcdb5 100644 --- a/tests/integration/test_register_persister.py +++ b/tests/integration/test_register_persister.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Tests for cassettes with custom persistence""" # External imports diff --git a/tests/integration/test_requests.py b/tests/integration/test_requests.py index c083dca7..b730fc24 100644 --- a/tests/integration/test_requests.py +++ b/tests/integration/test_requests.py @@ -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" diff --git a/tests/integration/test_tornado.py b/tests/integration/test_tornado.py index f0868a11..a3db0dd9 100644 --- a/tests/integration/test_tornado.py +++ b/tests/integration/test_tornado.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Test requests' interaction with vcr""" import json diff --git a/tests/integration/test_urllib2.py b/tests/integration/test_urllib2.py index 1133a40b..190fa8d4 100644 --- a/tests/integration/test_urllib2.py +++ b/tests/integration/test_urllib2.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Integration tests with urllib2""" import ssl diff --git a/tests/unit/test_migration.py b/tests/unit/test_migration.py index 8cee57df..36cb47b5 100644 --- a/tests/unit/test_migration.py +++ b/tests/unit/test_migration.py @@ -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 @@ -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 diff --git a/tests/unit/test_response.py b/tests/unit/test_response.py index 30d82e7c..2023c71e 100644 --- a/tests/unit/test_response.py +++ b/tests/unit/test_response.py @@ -1,4 +1,3 @@ -# coding: UTF-8 import io from vcr.stubs import VCRHTTPResponse diff --git a/tests/unit/test_serialize.py b/tests/unit/test_serialize.py index 0698ad86..7dd8a45f 100644 --- a/tests/unit/test_serialize.py +++ b/tests/unit/test_serialize.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- from unittest import mock import pytest @@ -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) diff --git a/tox.ini b/tox.ini index 0c4dd706..be389abd 100644 --- a/tox.ini +++ b/tox.ini @@ -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, @@ -12,7 +12,6 @@ envlist = [gh-actions] python = - 3.7: py37 3.8: py38 3.9: py39 3.10: py310, lint @@ -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 @@ -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 diff --git a/vcr/cassette.py b/vcr/cassette.py index 5822afac..92368763 100644 --- a/vcr/cassette.py +++ b/vcr/cassette.py @@ -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): @@ -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): @@ -356,7 +356,7 @@ def _load(self): pass def __str__(self): - return "".format(len(self)) + return f"" def __len__(self): """Return the number of request,response pairs stored in here""" diff --git a/vcr/config.py b/vcr/config.py index 5ee9f326..bb434b54 100644 --- a/vcr/config.py +++ b/vcr/config.py @@ -6,8 +6,6 @@ from collections import abc as collections_abc from pathlib import Path -import six - from . import filters, matchers from .cassette import Cassette from .persisters.filesystem import FilesystemPersister @@ -88,7 +86,7 @@ def _get_serializer(self, serializer_name): try: serializer = self.serializers[serializer_name] except KeyError: - raise KeyError("Serializer {} doesn't exist or isn't registered".format(serializer_name)) + raise KeyError(f"Serializer {serializer_name} doesn't exist or isn't registered") return serializer def _get_matchers(self, matcher_names): @@ -97,7 +95,7 @@ def _get_matchers(self, matcher_names): for m in matcher_names: matchers.append(self.matchers[m]) except KeyError: - raise KeyError("Matcher {} doesn't exist or isn't registered".format(m)) + raise KeyError(f"Matcher {m} doesn't exist or isn't registered") return matchers def use_cassette(self, path=None, **kwargs): @@ -253,5 +251,4 @@ def register_persister(self, persister): def test_case(self, predicate=None): predicate = predicate or self.is_test_method - # TODO: Remove this reference to `six` in favor of the Python3 equivalent - return six.with_metaclass(auto_decorate(self.use_cassette, predicate)) + return auto_decorate(self.use_cassette, predicate) diff --git a/vcr/matchers.py b/vcr/matchers.py index 5ed288a7..2817789a 100644 --- a/vcr/matchers.py +++ b/vcr/matchers.py @@ -9,31 +9,31 @@ def method(r1, r2): - assert r1.method == r2.method, "{} != {}".format(r1.method, r2.method) + assert r1.method == r2.method, f"{r1.method} != {r2.method}" def uri(r1, r2): - assert r1.uri == r2.uri, "{} != {}".format(r1.uri, r2.uri) + assert r1.uri == r2.uri, f"{r1.uri} != {r2.uri}" def host(r1, r2): - assert r1.host == r2.host, "{} != {}".format(r1.host, r2.host) + assert r1.host == r2.host, f"{r1.host} != {r2.host}" def scheme(r1, r2): - assert r1.scheme == r2.scheme, "{} != {}".format(r1.scheme, r2.scheme) + assert r1.scheme == r2.scheme, f"{r1.scheme} != {r2.scheme}" def port(r1, r2): - assert r1.port == r2.port, "{} != {}".format(r1.port, r2.port) + assert r1.port == r2.port, f"{r1.port} != {r2.port}" def path(r1, r2): - assert r1.path == r2.path, "{} != {}".format(r1.path, r2.path) + assert r1.path == r2.path, f"{r1.path} != {r2.path}" def query(r1, r2): - assert r1.query == r2.query, "{} != {}".format(r1.query, r2.query) + assert r1.query == r2.query, f"{r1.query} != {r2.query}" def raw_body(r1, r2): @@ -49,7 +49,7 @@ def body(r1, r2): def headers(r1, r2): - assert r1.headers == r2.headers, "{} != {}".format(r1.headers, r2.headers) + assert r1.headers == r2.headers, f"{r1.headers} != {r2.headers}" def _header_checker(value, header="Content-Type"): diff --git a/vcr/migration.py b/vcr/migration.py index b72d78ba..e24e937e 100644 --- a/vcr/migration.py +++ b/vcr/migration.py @@ -55,7 +55,7 @@ def build_uri(**parts): port = parts["port"] scheme = parts["protocol"] default_port = {"https": 443, "http": 80}[scheme] - parts["port"] = ":{}".format(port) if port != default_port else "" + parts["port"] = f":{port}" if port != default_port else "" return "{protocol}://{host}{port}{path}".format(**parts) @@ -118,7 +118,7 @@ def migrate(file_path, migration_fn): # because we assume that original files can be reverted # we will try to copy the content. (os.rename not needed) with tempfile.TemporaryFile(mode="w+") as out_fp: - with open(file_path, "r") as in_fp: + with open(file_path) as in_fp: if not migration_fn(in_fp, out_fp): return False with open(file_path, "w") as in_fp: @@ -150,7 +150,7 @@ def main(): for file_path in files: migrated = try_migrate(file_path) status = "OK" if migrated else "FAIL" - sys.stderr.write("[{}] {}\n".format(status, file_path)) + sys.stderr.write(f"[{status}] {file_path}\n") sys.stderr.write("Done.\n") diff --git a/vcr/patch.py b/vcr/patch.py index 632a15a8..a5ba6fab 100644 --- a/vcr/patch.py +++ b/vcr/patch.py @@ -186,9 +186,7 @@ def _build_cassette_subclass(self, base_class): bases = (base_class,) if not issubclass(base_class, object): # Check for old style class bases += (object,) - return type( - "{}{}".format(base_class.__name__, self._cassette._path), bases, dict(cassette=self._cassette) - ) + return type(f"{base_class.__name__}{self._cassette._path}", bases, dict(cassette=self._cassette)) @_build_patchers_from_mock_triples_decorator def _httplib(self): diff --git a/vcr/request.py b/vcr/request.py index dbda4f06..8b163486 100644 --- a/vcr/request.py +++ b/vcr/request.py @@ -90,7 +90,7 @@ def protocol(self): return self.scheme def __str__(self): - return "".format(self.method, self.uri) + return f"" def __repr__(self): return self.__str__() diff --git a/vcr/stubs/__init__.py b/vcr/stubs/__init__.py index 54ce470c..8d37b525 100644 --- a/vcr/stubs/__init__.py +++ b/vcr/stubs/__init__.py @@ -178,26 +178,26 @@ def _port_postfix(self): """ port = self.real_connection.port default_port = {"https": 443, "http": 80}[self._protocol] - return ":{}".format(port) if port != default_port else "" + return f":{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 = "{}://{}{}{}".format(self._protocol, self.real_connection.host, self._port_postfix(), url) + uri = f"{self._protocol}://{self.real_connection.host}{self._port_postfix()}{url}" log.debug("Absolute URI: %s", uri) return uri def _url(self, uri): """Returns request selector url from absolute URI""" - prefix = "{}://{}{}".format(self._protocol, self.real_connection.host, self._port_postfix()) + prefix = f"{self._protocol}://{self.real_connection.host}{self._port_postfix()}" return uri.replace(prefix, "", 1) def request(self, method, url, body=None, headers=None, *args, **kwargs): """Persist the request metadata in self._vcr_request""" self._vcr_request = Request(method=method, uri=self._uri(url), body=body, headers=headers or {}) - log.debug("Got {}".format(self._vcr_request)) + log.debug(f"Got {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 @@ -213,7 +213,7 @@ def putrequest(self, method, url, *args, **kwargs): of putheader() calls. """ self._vcr_request = Request(method=method, uri=self._uri(url), body="", headers={}) - log.debug("Got {}".format(self._vcr_request)) + log.debug(f"Got {self._vcr_request}") def putheader(self, header, *values): self._vcr_request.headers[header] = values @@ -245,7 +245,7 @@ def getresponse(self, _=False, **kwargs): # Check to see if the cassette has a response for this request. If so, # then return it if self.cassette.can_play_response_for(self._vcr_request): - log.info("Playing response for {} from cassette".format(self._vcr_request)) + log.info(f"Playing response for {self._vcr_request} from cassette") response = self.cassette.play_response(self._vcr_request) return VCRHTTPResponse(response) else: @@ -257,7 +257,7 @@ def getresponse(self, _=False, **kwargs): # Otherwise, we should send the request, then get the response # and return it. - log.info("{} not in cassette, sending to real server".format(self._vcr_request)) + log.info(f"{self._vcr_request} not in cassette, sending to real server") # This is imported here to avoid circular import. # TODO(@IvanMalison): Refactor to allow normal import. from vcr.patch import force_reset diff --git a/vcr/stubs/aiohttp_stubs.py b/vcr/stubs/aiohttp_stubs.py index 02fa4df3..4541b735 100644 --- a/vcr/stubs/aiohttp_stubs.py +++ b/vcr/stubs/aiohttp_stubs.py @@ -261,7 +261,7 @@ async def new_request(self, method, url, **kwargs): vcr_request = Request(method, str(request_url), data, _serialize_headers(headers)) if cassette.can_play_response_for(vcr_request): - log.info("Playing response for {} from cassette".format(vcr_request)) + log.info(f"Playing response for {vcr_request} from cassette") response = play_responses(cassette, vcr_request, kwargs) for redirect in response.history: self._cookie_jar.update_cookies(redirect.cookies, redirect.url) diff --git a/vcr/unittest.py b/vcr/unittest.py index 28433286..27c6c20f 100644 --- a/vcr/unittest.py +++ b/vcr/unittest.py @@ -32,7 +32,7 @@ def _get_cassette_library_dir(self): return os.path.join(testdir, "cassettes") def _get_cassette_name(self): - return "{0}.{1}.yaml".format(self.__class__.__name__, self._testMethodName) + return f"{self.__class__.__name__}.{self._testMethodName}.yaml" class VCRTestCase(VCRMixin, unittest.TestCase): diff --git a/vcr/util.py b/vcr/util.py index 5c53e246..9b5740e0 100644 --- a/vcr/util.py +++ b/vcr/util.py @@ -1,9 +1,5 @@ import types - -try: - from collections.abc import Mapping, MutableMapping -except ImportError: - from collections import Mapping, MutableMapping +from collections.abc import Mapping, MutableMapping # Shamelessly stolen from https://github.com/kennethreitz/requests/blob/master/requests/structures.py