]> git.ipfire.org Git - thirdparty/starlette.git/commitdiff
Drop Python 3.8 (#2823)
authorMarcelo Trylesinski <marcelotryle@gmail.com>
Sat, 28 Dec 2024 15:50:16 +0000 (16:50 +0100)
committerGitHub <noreply@github.com>
Sat, 28 Dec 2024 15:50:16 +0000 (16:50 +0100)
20 files changed:
.github/workflows/test-suite.yml
pyproject.toml
requirements.txt
starlette/_compat.py [deleted file]
starlette/_exception_handler.py
starlette/middleware/__init__.py
starlette/responses.py
tests/middleware/test_base.py
tests/middleware/test_wsgi.py
tests/test_applications.py
tests/test_authentication.py
tests/test_concurrency.py
tests/test_convertors.py
tests/test_endpoints.py
tests/test_exceptions.py
tests/test_formparsers.py
tests/test_requests.py
tests/test_responses.py
tests/test_testclient.py
tests/test_websockets.py

index fac94603928643768cd5caf0f115eeda4073d3be..14567a26e5d55d8ef6589d8d8e7f7de634b5e1e7 100644 (file)
@@ -14,7 +14,7 @@ jobs:
 
     strategy:
       matrix:
-        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
+        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
 
     steps:
       - uses: "actions/checkout@v4"
index 0712fe5da598593ed26d4358d31cc2dd0940e48b..51acf73556bafaa1afdb4718a07390820114bf90 100644 (file)
@@ -8,7 +8,7 @@ dynamic = ["version"]
 description = "The little ASGI library that shines."
 readme = "README.md"
 license = "BSD-3-Clause"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 authors = [{ name = "Tom Christie", email = "tom@tomchristie.com" }]
 classifiers = [
     "Development Status :: 3 - Alpha",
@@ -18,7 +18,6 @@ classifiers = [
     "License :: OSI Approved :: BSD License",
     "Operating System :: OS Independent",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
@@ -70,7 +69,7 @@ combine-as-imports = true
 [tool.mypy]
 strict = true
 ignore_missing_imports = true
-python_version = "3.8"
+python_version = "3.9"
 
 [[tool.mypy.overrides]]
 module = "starlette.testclient.*"
index fc147263dead3001be5f6d80902c9d21c130ac1a..83c34fc9c3ee0d1cbc65682ee59d9933dbd46d13 100644 (file)
@@ -14,11 +14,10 @@ pytest==8.3.4
 trio==0.27.0
 
 # Documentation
-black==24.10.0; python_version >= "3.9"
+black==24.10.0
 mkdocs==1.6.1
 mkdocs-material==9.5.47
-mkdocstrings-python<1.12.0; python_version < "3.9"
-mkdocstrings-python==1.12.2; python_version >= "3.9"
+mkdocstrings-python==1.12.2
 
 # Packaging
 build==1.2.2.post1
diff --git a/starlette/_compat.py b/starlette/_compat.py
deleted file mode 100644 (file)
index 718bc90..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-import hashlib
-
-# Compat wrapper to always include the `usedforsecurity=...` parameter,
-# which is only added from Python 3.9 onwards.
-# We use this flag to indicate that we use `md5` hashes only for non-security
-# cases (our ETag checksums).
-# If we don't indicate that we're using MD5 for non-security related reasons,
-# then attempting to use this function will raise an error when used
-# environments which enable a strict "FIPs mode".
-#
-# See issue: https://github.com/encode/starlette/issues/1365
-try:
-    # check if the Python version supports the parameter
-    # using usedforsecurity=False to avoid an exception on FIPS systems
-    # that reject usedforsecurity=True
-    hashlib.md5(b"data", usedforsecurity=False)  # type: ignore[call-arg]
-
-    def md5_hexdigest(data: bytes, *, usedforsecurity: bool = True) -> str:  # pragma: no cover
-        return hashlib.md5(  # type: ignore[call-arg]
-            data, usedforsecurity=usedforsecurity
-        ).hexdigest()
-
-except TypeError:  # pragma: no cover
-
-    def md5_hexdigest(data: bytes, *, usedforsecurity: bool = True) -> str:
-        return hashlib.md5(data).hexdigest()
index baf6e2f50e8e3e518ab1901e4a6a5c117246aba3..72bc89d91a4e7c2400511e280c26dd1cb2fc6502 100644 (file)
@@ -9,8 +9,8 @@ from starlette.requests import Request
 from starlette.types import ASGIApp, ExceptionHandler, Message, Receive, Scope, Send
 from starlette.websockets import WebSocket
 
-ExceptionHandlers = typing.Dict[typing.Any, ExceptionHandler]
-StatusHandlers = typing.Dict[int, ExceptionHandler]
+ExceptionHandlers = dict[typing.Any, ExceptionHandler]
+StatusHandlers = dict[int, ExceptionHandler]
 
 
 def _lookup_exception_handler(exc_handlers: ExceptionHandlers, exc: Exception) -> ExceptionHandler | None:
index 5164e49e044dce0050c4e93667608f37b791b543..b99538a272d985e5288faff04d2e7971b938d613 100644 (file)
@@ -1,7 +1,8 @@
 from __future__ import annotations
 
 import sys
-from typing import Any, Iterator, Protocol
+from collections.abc import Iterator
+from typing import Any, Protocol
 
 if sys.version_info >= (3, 10):  # pragma: no cover
     from typing import ParamSpec
index c711dfa39b28cd880b3983ce68c5af928b7dc869..31874f655b96be7e36ddb67faaf4c3bd223f5372 100644 (file)
@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+import hashlib
 import http.cookies
 import json
 import os
@@ -17,7 +18,6 @@ from urllib.parse import quote
 import anyio
 import anyio.to_thread
 
-from starlette._compat import md5_hexdigest
 from starlette.background import BackgroundTask
 from starlette.concurrency import iterate_in_threadpool
 from starlette.datastructures import URL, Headers, MutableHeaders
@@ -328,7 +328,7 @@ class FileResponse(Response):
         content_length = str(stat_result.st_size)
         last_modified = formatdate(stat_result.st_mtime, usegmt=True)
         etag_base = str(stat_result.st_mtime) + "-" + str(stat_result.st_size)
-        etag = f'"{md5_hexdigest(etag_base.encode(), usedforsecurity=False)}"'
+        etag = f'"{hashlib.md5(etag_base.encode(), usedforsecurity=False).hexdigest()}"'
 
         self.headers.setdefault("content-length", content_length)
         self.headers.setdefault("last-modified", last_modified)
index 449624e2f138488bcdadbdd551c06a34d5a673fa..7232cfd18de02a33056988ffe835a8afe774415d 100644 (file)
@@ -1,8 +1,9 @@
 from __future__ import annotations
 
 import contextvars
+from collections.abc import AsyncGenerator, AsyncIterator, Generator
 from contextlib import AsyncExitStack
-from typing import Any, AsyncGenerator, AsyncIterator, Generator
+from typing import Any
 
 import anyio
 import pytest
index e4ac66ab4eefd4b9f5aace3a361fca4a513b4a4b..3511c89c9623a3d6366d1551c52c662aa63c014d 100644 (file)
@@ -1,5 +1,6 @@
 import sys
-from typing import Any, Callable, Dict, Iterable
+from collections.abc import Iterable
+from typing import Any, Callable
 
 import pytest
 
@@ -9,7 +10,7 @@ from tests.types import TestClientFactory
 
 WSGIResponse = Iterable[bytes]
 StartResponse = Callable[..., Any]
-Environment = Dict[str, Any]
+Environment = dict[str, Any]
 
 
 def hello_world(
index db2a6050b9f6d2843922a02014875b780c44615a..310eef6b40dc915394bb693afa29c5dcc295a70c 100644 (file)
@@ -1,9 +1,10 @@
 from __future__ import annotations
 
 import os
+from collections.abc import AsyncGenerator, AsyncIterator, Generator
 from contextlib import asynccontextmanager
 from pathlib import Path
-from typing import AsyncGenerator, AsyncIterator, Callable, Generator
+from typing import Callable
 
 import anyio.from_thread
 import pytest
index 40886cd236351e95757ffda32d6aea8e8c0fdcb9..ddd2ad805044e43101cccd5da0bf0979c4bbfb8b 100644 (file)
@@ -2,19 +2,14 @@ from __future__ import annotations
 
 import base64
 import binascii
-from typing import Any, Awaitable, Callable
+from collections.abc import Awaitable
+from typing import Any, Callable
 from urllib.parse import urlencode
 
 import pytest
 
 from starlette.applications import Starlette
-from starlette.authentication import (
-    AuthCredentials,
-    AuthenticationBackend,
-    AuthenticationError,
-    SimpleUser,
-    requires,
-)
+from starlette.authentication import AuthCredentials, AuthenticationBackend, AuthenticationError, SimpleUser, requires
 from starlette.endpoints import HTTPEndpoint
 from starlette.middleware import Middleware
 from starlette.middleware.authentication import AuthenticationMiddleware
index 380eb9ef2ae4a7dcec41cf0d3a16b6e52190923c..d620984c11bdae18aa64990b7667cea300383424 100644 (file)
@@ -1,5 +1,5 @@
+from collections.abc import Iterator
 from contextvars import ContextVar
-from typing import Iterator
 
 import anyio
 import pytest
index 0fabe101b87b88a00a617c79898a19efe2bb5950..d8430c672ad1dd81db0c9b14ba5b0deb763504dc 100644 (file)
@@ -1,5 +1,5 @@
+from collections.abc import Iterator
 from datetime import datetime
-from typing import Iterator
 from uuid import UUID
 
 import pytest
index 42776a5b32243fd6ebccde8771ff43ac62eb01d5..76163873c15ca544badb7256aa0bd348b7acfcc3 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Iterator
+from collections.abc import Iterator
 
 import pytest
 
index ffc8883b3c721a1f7f27819fa7d758a63ce92cba..ff291325411c27e161724df2d2fdbf27701130ab 100644 (file)
@@ -1,5 +1,5 @@
 import warnings
-from typing import Generator
+from collections.abc import Generator
 
 import pytest
 
index f781a9ecb302abf6b81e911127e233f0d13905a2..70beebc3f3338ebca27f57e5bb8576b403ed5a7b 100644 (file)
@@ -17,7 +17,7 @@ from starlette.types import ASGIApp, Receive, Scope, Send
 from tests.types import TestClientFactory
 
 
-class ForceMultipartDict(typing.Dict[typing.Any, typing.Any]):
+class ForceMultipartDict(dict[typing.Any, typing.Any]):
     def __bool__(self) -> bool:
         return True
 
index 665dceb87527cb326c1c25f743f07dd1116b065c..7e2c608dc4c9e41bc655473754ac35c4da88e843 100644 (file)
@@ -1,7 +1,8 @@
 from __future__ import annotations
 
 import sys
-from typing import Any, Iterator
+from collections.abc import Iterator
+from typing import Any
 
 import anyio
 import pytest
index 28f2feb2d647d111c1362d69636ac7a4566090f5..d5ed83499831122db593cf3259318346226c4f3a 100644 (file)
@@ -2,9 +2,10 @@ from __future__ import annotations
 
 import datetime as dt
 import time
+from collections.abc import AsyncGenerator, AsyncIterator, Iterator
 from http.cookies import SimpleCookie
 from pathlib import Path
-from typing import Any, AsyncGenerator, AsyncIterator, Iterator
+from typing import Any
 
 import anyio
 import pytest
index 279b81d918be918c40b589f5170a90012872382c..58ab6f6f23123e80703c7135c4412f5b331df198 100644 (file)
@@ -3,8 +3,9 @@ from __future__ import annotations
 import itertools
 import sys
 from asyncio import Task, current_task as asyncio_current_task
+from collections.abc import AsyncGenerator
 from contextlib import asynccontextmanager
-from typing import Any, AsyncGenerator
+from typing import Any
 
 import anyio
 import anyio.lowlevel
index 8ecf6304c88ab3be9659d298923ed261fe129cb8..e76d8f29ba857ceee08f6db911e8f81d1664c8a4 100644 (file)
@@ -1,5 +1,6 @@
 import sys
-from typing import Any, MutableMapping
+from collections.abc import MutableMapping
+from typing import Any
 
 import anyio
 import pytest