From b8d144d49106e14ab6bfcf40a5b8aea7639d6150 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sun, 19 May 2024 16:18:49 -0400 Subject: [PATCH] Add 3.13 to our CI (#11926) --- .github/workflows/tests.yml | 28 ++++++++++++++++++++++++---- stdlib/logging/__init__.pyi | 3 ++- stubs/WebOb/webob/multidict.pyi | 11 ++++++++--- stubs/WebOb/webob/request.pyi | 13 ++++++++++--- tests/mypy_test.py | 2 +- tests/regr_test.py | 2 +- tests/runtests.py | 2 +- tests/typecheck_typeshed.py | 2 +- 8 files changed, 48 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 593934293..a1b0dc0ab 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -73,6 +73,26 @@ jobs: - run: uv pip install -r requirements-tests.txt --system - run: python ./tests/mypy_test.py --platform=${{ matrix.platform }} --python-version=${{ matrix.python-version }} + # Run this as a separate job, as the other versions in the matrix are + # (and should be) run *using* the Python version we're testing the stubs for, + # but we can't install all our non-types dependencies on py313 yet + mypy-313: + name: Run mypy against the 3.13 stubs + runs-on: ubuntu-latest + strategy: + matrix: + platform: ["linux", "win32", "darwin"] + fail-fast: false + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.12 + allow-prereleases: true + - run: curl -LsSf https://astral.sh/uv/install.sh | sh + - run: uv pip install -r requirements-tests.txt --system + - run: python ./tests/mypy_test.py --platform=${{ matrix.platform }} --python-version=3.13 + regression-tests: name: Run mypy on the test cases runs-on: ubuntu-latest @@ -93,7 +113,7 @@ jobs: strategy: matrix: python-platform: ["Linux", "Windows", "Darwin"] - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] fail-fast: false steps: - uses: actions/checkout@v4 @@ -125,14 +145,14 @@ jobs: version: PATH python-platform: ${{ matrix.python-platform }} python-version: ${{ matrix.python-version }} - annotate: ${{ matrix.python-version == '3.11' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy. + annotate: ${{ matrix.python-version == '3.12' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy. - name: Run pyright with stricter settings on some of the stubs uses: jakebailey/pyright-action@v2 with: version: PATH python-platform: ${{ matrix.python-platform }} python-version: ${{ matrix.python-version }} - annotate: ${{ matrix.python-version == '3.11' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy. + annotate: ${{ matrix.python-version == '3.12' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy. project: ./pyrightconfig.stricter.json - name: Run pyright on the test cases uses: jakebailey/pyright-action@v2 @@ -140,7 +160,7 @@ jobs: version: PATH python-platform: ${{ matrix.python-platform }} python-version: ${{ matrix.python-version }} - annotate: ${{ matrix.python-version == '3.11' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy. + annotate: ${{ matrix.python-version == '3.12' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy. project: ./pyrightconfig.testcases.json stub-uploader: diff --git a/stdlib/logging/__init__.pyi b/stdlib/logging/__init__.pyi index 0b7c3327f..daae70707 100644 --- a/stdlib/logging/__init__.pyi +++ b/stdlib/logging/__init__.pyi @@ -50,7 +50,6 @@ __all__ = [ "makeLogRecord", "setLoggerClass", "shutdown", - "warn", "warning", "getLogRecordFactory", "setLogRecordFactory", @@ -58,6 +57,8 @@ __all__ = [ "raiseExceptions", ] +if sys.version_info < (3, 13): + __all__ += ["warn"] if sys.version_info >= (3, 11): __all__ += ["getLevelNamesMapping"] if sys.version_info >= (3, 12): diff --git a/stubs/WebOb/webob/multidict.pyi b/stubs/WebOb/webob/multidict.pyi index 75a58d107..b1aa4a510 100644 --- a/stubs/WebOb/webob/multidict.pyi +++ b/stubs/WebOb/webob/multidict.pyi @@ -1,9 +1,14 @@ +import sys from _typeshed import SupportsItems, SupportsKeysAndGetItem from _typeshed.wsgi import WSGIEnvironment -from cgi import FieldStorage from collections.abc import Collection, Iterable, Iterator, MutableMapping from typing import Any, Literal, TypeVar, overload -from typing_extensions import Self +from typing_extensions import Self, TypeAlias + +if sys.version_info >= (3, 13): + _FieldStorage: TypeAlias = Any +else: + from cgi import FieldStorage as _FieldStorage _T = TypeVar("_T") _KT = TypeVar("_KT") @@ -19,7 +24,7 @@ class MultiDict(MutableMapping[_KT, _VT]): @classmethod def view_list(cls, lst: list[tuple[_KT, _VT]]) -> MultiDict[_KT, _VT]: ... @classmethod - def from_fieldstorage(cls, fs: FieldStorage) -> MultiDict[str, str | FieldStorage]: ... + def from_fieldstorage(cls, fs: _FieldStorage) -> MultiDict[str, str | _FieldStorage]: ... def __getitem__(self, key: _KT) -> _VT: ... def __setitem__(self, key: _KT, value: _VT) -> None: ... def add(self, key: _KT, value: _VT) -> None: ... diff --git a/stubs/WebOb/webob/request.pyi b/stubs/WebOb/webob/request.pyi index d57118866..4f9af63f9 100644 --- a/stubs/WebOb/webob/request.pyi +++ b/stubs/WebOb/webob/request.pyi @@ -1,8 +1,8 @@ import datetime import io +import sys from _typeshed import ExcInfo, ReadableBuffer, SupportsItems, SupportsKeysAndGetItem, SupportsNoArgReadline, SupportsRead from _typeshed.wsgi import WSGIApplication, WSGIEnvironment -from cgi import FieldStorage from collections.abc import Iterable, Mapping from re import Pattern from tempfile import _TemporaryFileWrapper @@ -19,6 +19,11 @@ from webob.headers import EnvironHeaders from webob.multidict import GetDict, MultiDict, NestedMultiDict, NoVars from webob.response import Response, _HTTPHeader +if sys.version_info >= (3, 13): + _FieldStorage: TypeAlias = Any +else: + from cgi import FieldStorage as _FieldStorage + _T = TypeVar("_T") _HTTPMethod: TypeAlias = Literal["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"] _ListOrTuple: TypeAlias = list[_T] | tuple[_T, ...] @@ -34,7 +39,9 @@ class _RequestCacheControlDict(TypedDict, total=False): no_transform: bool max_age: int -class _FieldStorageWithFile(FieldStorage): +# On py313 this subclasses `Any`, hence the type: ignore. +# This is needed for the regr_test.py script, which uses --disallow-subclassing-any +class _FieldStorageWithFile(_FieldStorage): # type: ignore[misc] file: IO[bytes] filename: str @@ -244,4 +251,4 @@ class Transcoder: errors: str def __init__(self, charset: str, errors: str = "strict") -> None: ... def transcode_query(self, q: str) -> str: ... - def transcode_fs(self, fs: FieldStorage, content_type: str) -> io.BytesIO: ... + def transcode_fs(self, fs: _FieldStorage, content_type: str) -> io.BytesIO: ... diff --git a/tests/mypy_test.py b/tests/mypy_test.py index a432dd41a..a603bd524 100755 --- a/tests/mypy_test.py +++ b/tests/mypy_test.py @@ -48,7 +48,7 @@ except ImportError: print_error("Cannot import mypy. Did you install it?") sys.exit(1) -SUPPORTED_VERSIONS = ["3.12", "3.11", "3.10", "3.9", "3.8"] +SUPPORTED_VERSIONS = ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8"] SUPPORTED_PLATFORMS = ("linux", "win32", "darwin") DIRECTORIES_TO_TEST = [Path("stdlib"), Path("stubs")] diff --git a/tests/regr_test.py b/tests/regr_test.py index 387c53ecf..144e822f6 100755 --- a/tests/regr_test.py +++ b/tests/regr_test.py @@ -40,7 +40,7 @@ VENV_DIR = ".venv" TYPESHED = "typeshed" SUPPORTED_PLATFORMS = ["linux", "darwin", "win32"] -SUPPORTED_VERSIONS = ["3.12", "3.11", "3.10", "3.9", "3.8"] +SUPPORTED_VERSIONS = ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8"] def distribution_with_test_cases(distribution_name: str) -> DistributionTests: diff --git a/tests/runtests.py b/tests/runtests.py index 697312659..b465bf6c0 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -62,7 +62,7 @@ def main() -> None: parser.add_argument( "--python-version", default=_PYTHON_VERSION, - choices=("3.8", "3.9", "3.10", "3.11", "3.12"), + choices=("3.8", "3.9", "3.10", "3.11", "3.12", "3.13"), help="Target Python version for the test (default: %(default)s).", ) parser.add_argument("path", help="Path of the stub to test in format /, from the root of the project.") diff --git a/tests/typecheck_typeshed.py b/tests/typecheck_typeshed.py index 32f30fd73..38e4a712b 100755 --- a/tests/typecheck_typeshed.py +++ b/tests/typecheck_typeshed.py @@ -13,7 +13,7 @@ from utils import colored, print_error ReturnCode: TypeAlias = int SUPPORTED_PLATFORMS = ("linux", "darwin", "win32") -SUPPORTED_VERSIONS = ("3.12", "3.11", "3.10", "3.9") +SUPPORTED_VERSIONS = ("3.13", "3.12", "3.11", "3.10", "3.9") LOWEST_SUPPORTED_VERSION = min(SUPPORTED_VERSIONS, key=lambda x: int(x.split(".")[1])) DIRECTORIES_TO_TEST = ("scripts", "tests") EMPTY: list[str] = []