Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Python 3.8 #2543

Merged
merged 2 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
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"]
os: [windows-latest, ubuntu-latest, macos-latest]
steps:
- uses: "actions/checkout@v4"
Expand Down
7 changes: 2 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ dynamic = ["version"]
description = "The lightning-fast ASGI server."
readme = "README.md"
license = "BSD-3-Clause"
requires-python = ">=3.8"
requires-python = ">=3.9"
authors = [
{ name = "Tom Christie", email = "[email protected]" },
{ name = "Marcelo Trylesinski", email = "[email protected]" },
Expand All @@ -20,7 +20,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",
Expand All @@ -38,7 +37,7 @@ dependencies = [

[project.optional-dependencies]
standard = [
"colorama>=0.4;sys_platform == 'win32'",
"colorama>=0.4; sys_platform == 'win32'",
"httptools>=0.6.3",
"python-dotenv>=0.13",
"PyYAML>=5.1",
Expand Down Expand Up @@ -127,8 +126,6 @@ py-win32 = "sys_platform == 'win32'"
py-not-win32 = "sys_platform != 'win32'"
py-linux = "sys_platform == 'linux'"
py-darwin = "sys_platform == 'darwin'"
py-gte-38 = "sys_version_info >= (3, 8)"
py-lt-38 = "sys_version_info < (3, 8)"
py-gte-39 = "sys_version_info >= (3, 9)"
py-lt-39 = "sys_version_info < (3, 9)"
py-gte-310 = "sys_version_info >= (3, 10)"
Expand Down
6 changes: 2 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ pytest-mock==3.14.0
mypy==1.13.0
types-click==7.1.8
types-pyyaml==6.0.12.20240917
trustme==1.1.0; python_version < '3.9'
trustme==1.2.0; python_version >= '3.9'
trustme==1.2.0
cryptography==44.0.0
coverage==7.6.1; python_version < '3.9'
coverage==7.6.9; python_version >= '3.9'
coverage==7.6.9
coverage-conditional-plugin==0.9.0
httpx==0.28.1

Expand Down
3 changes: 2 additions & 1 deletion tests/middleware/test_wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import io
import sys
from typing import AsyncGenerator, Callable
from collections.abc import AsyncGenerator
from typing import Callable

import a2wsgi
import httpx
Expand Down
3 changes: 2 additions & 1 deletion tests/supervisors/test_reload.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import signal
import socket
import sys
from collections.abc import Generator
from pathlib import Path
from threading import Thread
from time import sleep
from typing import Callable, Generator
from typing import Callable

import pytest
from pytest_mock import MockerFixture
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import os
import platform
import sys
from collections.abc import Iterator
from pathlib import Path
from textwrap import dedent
from typing import Iterator
from unittest import mock

import pytest
Expand Down
6 changes: 4 additions & 2 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import logging
import signal
import sys
from typing import Callable, ContextManager, Generator
from collections.abc import Generator
from contextlib import AbstractContextManager
from typing import Callable

import httpx
import pytest
Expand Down Expand Up @@ -62,7 +64,7 @@ async def app(scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable
@pytest.mark.parametrize("exception_signal", signals)
@pytest.mark.parametrize("capture_signal", signal_captures)
async def test_server_interrupt(
exception_signal: signal.Signals, capture_signal: Callable[[signal.Signals], ContextManager[None]]
exception_signal: signal.Signals, capture_signal: Callable[[signal.Signals], AbstractContextManager[None]]
): # pragma: py-win32
"""Test interrupting a Server that is run explicitly inside asyncio"""

Expand Down
22 changes: 5 additions & 17 deletions uvicorn/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,8 @@

import sys
import types
from typing import (
Any,
Awaitable,
Callable,
Iterable,
Literal,
MutableMapping,
Optional,
Protocol,
Tuple,
Type,
TypedDict,
Union,
)
from collections.abc import Awaitable, Iterable, MutableMapping
from typing import Any, Callable, Literal, Optional, Protocol, TypedDict, Union

if sys.version_info >= (3, 11): # pragma: py-lt-311
from typing import NotRequired
Expand All @@ -54,8 +42,8 @@

# WSGI
Environ = MutableMapping[str, Any]
ExcInfo = Tuple[Type[BaseException], BaseException, Optional[types.TracebackType]]
StartResponse = Callable[[str, Iterable[Tuple[str, str]], Optional[ExcInfo]], None]
ExcInfo = tuple[type[BaseException], BaseException, Optional[types.TracebackType]]
StartResponse = Callable[[str, Iterable[tuple[str, str]], Optional[ExcInfo]], None]
WSGIApp = Callable[[Environ, StartResponse], Union[Iterable[bytes], BaseException]]


Expand Down Expand Up @@ -281,7 +269,7 @@ def __init__(self, scope: Scope) -> None: ... # pragma: no cover
async def __call__(self, receive: ASGIReceiveCallable, send: ASGISendCallable) -> None: ... # pragma: no cover


ASGI2Application = Type[ASGI2Protocol]
ASGI2Application = type[ASGI2Protocol]
ASGI3Application = Callable[
[
Scope,
Expand Down
3 changes: 2 additions & 1 deletion uvicorn/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
import socket
import ssl
import sys
from collections.abc import Awaitable
from configparser import RawConfigParser
from pathlib import Path
from typing import IO, Any, Awaitable, Callable, Literal
from typing import IO, Any, Callable, Literal

import click

Expand Down
2 changes: 1 addition & 1 deletion uvicorn/middleware/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
import warnings
from collections import deque
from typing import Iterable
from collections.abc import Iterable

from uvicorn._types import (
ASGIReceiveCallable,
Expand Down
3 changes: 2 additions & 1 deletion uvicorn/protocols/websockets/websockets_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import asyncio
import http
import logging
from typing import Any, Literal, Optional, Sequence, cast
from collections.abc import Sequence
from typing import Any, Literal, Optional, cast
from urllib.parse import unquote

import websockets
Expand Down
8 changes: 3 additions & 5 deletions uvicorn/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
import sys
import threading
import time
from collections.abc import Generator, Sequence
from email.utils import formatdate
from types import FrameType
from typing import TYPE_CHECKING, Generator, Sequence, Union
from typing import TYPE_CHECKING, Union

import click

Expand Down Expand Up @@ -284,10 +285,7 @@ async def shutdown(self, sockets: list[socket.socket] | None = None) -> None:
len(self.server_state.tasks),
)
for t in self.server_state.tasks:
if sys.version_info < (3, 9): # pragma: py-gte-39
t.cancel()
else: # pragma: py-lt-39
t.cancel(msg="Task cancelled, timeout graceful shutdown exceeded")
t.cancel(msg="Task cancelled, timeout graceful shutdown exceeded")

# Send the lifespan shutdown event, and wait for application shutdown.
if not self.force_exit:
Expand Down
3 changes: 2 additions & 1 deletion uvicorn/supervisors/basereload.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import signal
import sys
import threading
from collections.abc import Iterator
from pathlib import Path
from socket import socket
from types import FrameType
from typing import Callable, Iterator
from typing import Callable

import click

Expand Down
3 changes: 2 additions & 1 deletion uvicorn/supervisors/statreload.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations

import logging
from collections.abc import Iterator
from pathlib import Path
from socket import socket
from typing import Callable, Iterator
from typing import Callable

from uvicorn.config import Config
from uvicorn.supervisors.basereload import BaseReload
Expand Down
Loading