From 5be5af3c900ef9ead3387a1193fc4ff4ad1e5594 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Tue, 20 Aug 2024 21:40:02 +0100 Subject: [PATCH] Drop Python 3.8 (#8797) --- .github/workflows/ci-cd.yml | 4 +--- .github/workflows/update-pre-commit.yml | 4 ++-- CHANGES/8797.breaking.rst | 1 + Makefile | 6 +----- aiohttp/cookiejar.py | 2 +- aiohttp/resolver.py | 6 ++---- aiohttp/web_fileresponse.py | 4 ---- setup.cfg | 3 +-- setup.py | 4 ++-- tests/test_resolver.py | 7 ------- 10 files changed, 11 insertions(+), 30 deletions(-) create mode 100644 CHANGES/8797.breaking.rst diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3096db57454..55f7d6570ad 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -141,15 +141,13 @@ jobs: needs: gen_llhttp strategy: matrix: - pyver: [3.8, 3.9, '3.10', '3.11', '3.12'] + pyver: [3.9, '3.10', '3.11', '3.12'] no-extensions: ['', 'Y'] os: [ubuntu, macos, windows] experimental: [false] exclude: - os: macos no-extensions: 'Y' - - os: macos - pyver: 3.8 - os: windows no-extensions: 'Y' include: diff --git a/.github/workflows/update-pre-commit.yml b/.github/workflows/update-pre-commit.yml index 880469b5e22..e5ddb3a016d 100644 --- a/.github/workflows/update-pre-commit.yml +++ b/.github/workflows/update-pre-commit.yml @@ -12,7 +12,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: >- pip install -r requirements/lint.in -c requirements/lint.txt @@ -33,4 +33,4 @@ jobs: body: | Update versions of tools in pre-commit configs to latest version - labels: dependencies backport-3.7 backport-3.8 + labels: dependencies backport-3.10 backport-3.11 diff --git a/CHANGES/8797.breaking.rst b/CHANGES/8797.breaking.rst new file mode 100644 index 00000000000..c219ea3d264 --- /dev/null +++ b/CHANGES/8797.breaking.rst @@ -0,0 +1 @@ +Dropped support for Python 3.8 -- by :user:`Dreamsorcerer`. diff --git a/Makefile b/Makefile index a1ef773d051..78538bea09b 100644 --- a/Makefile +++ b/Makefile @@ -117,11 +117,7 @@ define run_tests_in_docker docker run --rm -ti -v `pwd`:/src -w /src "aiohttp-test-$(1)-$(2)" $(TEST_SPEC) endef -.PHONY: test-3.8-no-extensions test-3.8 test-3.9-no-extensions test -test-3.8-no-extensions: - $(call run_tests_in_docker,3.8,y) -test-3.8: - $(call run_tests_in_docker,3.8,n) +.PHONY: test-3.9-no-extensions test test-3.9-no-extensions: $(call run_tests_in_docker,3.9,y) test-3.9: diff --git a/aiohttp/cookiejar.py b/aiohttp/cookiejar.py index e79e82878a3..569d03b6370 100644 --- a/aiohttp/cookiejar.py +++ b/aiohttp/cookiejar.py @@ -70,7 +70,7 @@ class CookieJar(AbstractCookieJar): except (OSError, ValueError): # Hit the maximum representable time on Windows # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64 - # Throws ValueError on PyPy 3.8 and 3.9, OSError elsewhere + # Throws ValueError on PyPy 3.9, OSError elsewhere MAX_TIME = calendar.timegm((3000, 12, 31, 23, 59, 59, -1, -1, -1)) except OverflowError: # #4515: datetime.max may not be representable on 32-bit platforms diff --git a/aiohttp/resolver.py b/aiohttp/resolver.py index 16abbdec2e9..85e2831a563 100644 --- a/aiohttp/resolver.py +++ b/aiohttp/resolver.py @@ -1,6 +1,5 @@ import asyncio import socket -import sys from typing import Any, List, Tuple, Type, Union from .abc import AbstractResolver, ResolveResult @@ -18,7 +17,6 @@ _NUMERIC_SOCKET_FLAGS = socket.AI_NUMERICHOST | socket.AI_NUMERICSERV -_SUPPORTS_SCOPE_ID = sys.version_info >= (3, 9, 0) class ThreadedResolver(AbstractResolver): @@ -49,7 +47,7 @@ async def resolve( # IPv6 is not supported by Python build, # or IPv6 is not enabled in the host continue - if address[3] and _SUPPORTS_SCOPE_ID: + if address[3]: # This is essential for link-local IPv6 addresses. # LL IPv6 is a VERY rare case. Strictly speaking, we should use # getnameinfo() unconditionally, but performance makes sense. @@ -107,7 +105,7 @@ async def resolve( address: Union[Tuple[bytes, int], Tuple[bytes, int, int, int]] = node.addr family = node.family if family == socket.AF_INET6: - if len(address) > 3 and address[3] and _SUPPORTS_SCOPE_ID: + if len(address) > 3 and address[3]: # This is essential for link-local IPv6 addresses. # LL IPv6 is a VERY rare case. Strictly speaking, we should use # getnameinfo() unconditionally, but performance makes sense. diff --git a/aiohttp/web_fileresponse.py b/aiohttp/web_fileresponse.py index 243dda6072f..8c49af6b781 100644 --- a/aiohttp/web_fileresponse.py +++ b/aiohttp/web_fileresponse.py @@ -1,7 +1,6 @@ import asyncio import os import pathlib -import sys from contextlib import suppress from mimetypes import MimeTypes from stat import S_ISREG @@ -45,9 +44,6 @@ CONTENT_TYPES: Final[MimeTypes] = MimeTypes() -if sys.version_info < (3, 9): - CONTENT_TYPES.encodings_map[".br"] = "br" - # File extension to IANA encodings map that will be checked in the order defined. ENCODING_EXTENSIONS = MappingProxyType( {ext: CONTENT_TYPES.encodings_map[ext] for ext in (".br", ".gz")} diff --git a/setup.cfg b/setup.cfg index 95bc462288f..15b66caffea 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,6 @@ classifiers = Programming Language :: Python Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 @@ -42,7 +41,7 @@ classifiers = Topic :: Internet :: WWW/HTTP [options] -python_requires = >=3.8 +python_requires = >=3.9 packages = aiohttp # https://setuptools.readthedocs.io/en/latest/setuptools.html#setting-the-zip-safe-flag zip_safe = False diff --git a/setup.py b/setup.py index 2622e5c5223..ce38273c573 100644 --- a/setup.py +++ b/setup.py @@ -4,8 +4,8 @@ from setuptools import Extension, setup -if sys.version_info < (3, 8): - raise RuntimeError("aiohttp 4.x requires Python 3.8+") +if sys.version_info < (3, 9): + raise RuntimeError("aiohttp 4.x requires Python 3.9+") NO_EXTENSIONS: bool = bool(os.environ.get("AIOHTTP_NO_EXTENSIONS")) diff --git a/tests/test_resolver.py b/tests/test_resolver.py index 67e0e915196..33defd990f2 100644 --- a/tests/test_resolver.py +++ b/tests/test_resolver.py @@ -9,7 +9,6 @@ from aiohttp.resolver import ( _NUMERIC_SOCKET_FLAGS, - _SUPPORTS_SCOPE_ID, AsyncResolver, DefaultResolver, ThreadedResolver, @@ -138,9 +137,6 @@ async def test_async_resolver_positive_ipv4_lookup(loop: Any) -> None: @pytest.mark.skipif(not getaddrinfo, reason="aiodns >=3.2.0 required") -@pytest.mark.skipif( - not _SUPPORTS_SCOPE_ID, reason="python version does not support scope id" -) async def test_async_resolver_positive_link_local_ipv6_lookup(loop: Any) -> None: with patch("aiodns.DNSResolver") as mock: mock().getaddrinfo.return_value = fake_aiodns_getaddrinfo_ipv6_result( @@ -203,9 +199,6 @@ async def test_threaded_resolver_positive_lookup() -> None: ipaddress.ip_address(real[0]["host"]) -@pytest.mark.skipif( - not _SUPPORTS_SCOPE_ID, reason="python version does not support scope id" -) async def test_threaded_resolver_positive_ipv6_link_local_lookup() -> None: loop = Mock() loop.getaddrinfo = fake_ipv6_addrinfo(["fe80::1"])