Drop support for Python 3.8 (#8183)

Co-authored-by: Andrew Murray <radarhere@users.noreply.github.com>
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
This commit is contained in:
Hugo van Kemenade 2024-07-03 00:44:45 -06:00 committed by GitHub
parent 7537ce8a60
commit 51bd7d2ea8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 66 additions and 67 deletions

View File

@ -21,9 +21,9 @@ environment:
- PYTHON: C:/Python312 - PYTHON: C:/Python312
ARCHITECTURE: x86 ARCHITECTURE: x86
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
- PYTHON: C:/Python38-x64 - PYTHON: C:/Python39-x64
ARCHITECTURE: AMD64 ARCHITECTURE: AMD64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
install: install:
@ -38,7 +38,7 @@ install:
- path c:\nasm-2.16.03;C:\Program Files\gs\gs10.03.1\bin;%PATH% - path c:\nasm-2.16.03;C:\Program Files\gs\gs10.03.1\bin;%PATH%
- cd c:\pillow\winbuild\ - cd c:\pillow\winbuild\
- ps: | - ps: |
c:\python38\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\ c:\python39\python.exe c:\pillow\winbuild\build_prepare.py -v --depends=C:\pillow-depends\
c:\pillow\winbuild\build\build_dep_all.cmd c:\pillow\winbuild\build\build_dep_all.cmd
$host.SetShouldExit(0) $host.SetShouldExit(0)
- path C:\pillow\winbuild\build\bin;%PATH% - path C:\pillow\winbuild\build\bin;%PATH%

View File

@ -48,7 +48,6 @@ if [[ $(uname) != CYGWIN* ]]; then
# Pyroma uses non-isolated build and fails with old setuptools # Pyroma uses non-isolated build and fails with old setuptools
if [[ if [[
$GHA_PYTHON_VERSION == pypy3.9 $GHA_PYTHON_VERSION == pypy3.9
|| $GHA_PYTHON_VERSION == 3.8
|| $GHA_PYTHON_VERSION == 3.9 || $GHA_PYTHON_VERSION == 3.9
]]; then ]]; then
# To match pyproject.toml # To match pyproject.toml

View File

@ -35,7 +35,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-minor-version: [8, 9] python-minor-version: [9]
timeout-minutes: 40 timeout-minutes: 40

View File

@ -49,7 +49,6 @@ jobs:
fedora-39-amd64, fedora-39-amd64,
fedora-40-amd64, fedora-40-amd64,
gentoo, gentoo,
ubuntu-20.04-focal-amd64,
ubuntu-22.04-jammy-amd64, ubuntu-22.04-jammy-amd64,
ubuntu-24.04-noble-amd64, ubuntu-24.04-noble-amd64,
] ]

View File

@ -35,7 +35,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["pypy3.10", "pypy3.9", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] python-version: ["pypy3.10", "pypy3.9", "3.9", "3.10", "3.11", "3.12", "3.13"]
timeout-minutes: 30 timeout-minutes: 30

View File

@ -48,7 +48,6 @@ jobs:
"3.11", "3.11",
"3.10", "3.10",
"3.9", "3.9",
"3.8",
] ]
include: include:
- python-version: "3.11" - python-version: "3.11"
@ -59,13 +58,9 @@ jobs:
# M1 only available for 3.10+ # M1 only available for 3.10+
- os: "macos-13" - os: "macos-13"
python-version: "3.9" python-version: "3.9"
- os: "macos-13"
python-version: "3.8"
exclude: exclude:
- os: "macos-14" - os: "macos-14"
python-version: "3.9" python-version: "3.9"
- os: "macos-14"
python-version: "3.8"
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
name: ${{ matrix.os }} Python ${{ matrix.python-version }} name: ${{ matrix.os }} Python ${{ matrix.python-version }}

View File

@ -41,7 +41,6 @@ jobs:
python-version: python-version:
- pp39 - pp39
- pp310 - pp310
- cp38
- cp39 - cp39
- cp310 - cp310
- cp311 - cp311
@ -136,8 +135,6 @@ jobs:
CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }} CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }}
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }} CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }}
CIBW_PRERELEASE_PYTHONS: True CIBW_PRERELEASE_PYTHONS: True
CIBW_SKIP: pp38-*
CIBW_TEST_SKIP: cp38-macosx_arm64
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }} MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
@ -208,7 +205,6 @@ jobs:
CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd" CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd"
CIBW_CACHE_PATH: "C:\\cibw" CIBW_CACHE_PATH: "C:\\cibw"
CIBW_PRERELEASE_PYTHONS: True CIBW_PRERELEASE_PYTHONS: True
CIBW_SKIP: pp38-*
CIBW_TEST_SKIP: "*-win_arm64" CIBW_TEST_SKIP: "*-win_arm64"
CIBW_TEST_COMMAND: 'docker run --rm CIBW_TEST_COMMAND: 'docker run --rm
-v {project}:C:\pillow -v {project}:C:\pillow

View File

@ -11,9 +11,10 @@ import subprocess
import sys import sys
import sysconfig import sysconfig
import tempfile import tempfile
from collections.abc import Sequence
from functools import lru_cache from functools import lru_cache
from io import BytesIO from io import BytesIO
from typing import Any, Callable, Sequence from typing import Any, Callable
import pytest import pytest
from packaging.version import parse as parse_version from packaging.version import parse as parse_version

View File

@ -385,9 +385,10 @@ def test_timeout(test_file: str) -> None:
def test_bounding_box_in_trailer() -> None: def test_bounding_box_in_trailer() -> None:
# Check bounding boxes are parsed in the same way # Check bounding boxes are parsed in the same way
# when specified in the header and the trailer # when specified in the header and the trailer
with Image.open("Tests/images/zero_bb_trailer.eps") as trailer_image, Image.open( with (
FILE1 Image.open("Tests/images/zero_bb_trailer.eps") as trailer_image,
) as header_image: Image.open(FILE1) as header_image,
):
assert trailer_image.size == header_image.size assert trailer_image.size == header_image.size

View File

@ -1,9 +1,9 @@
from __future__ import annotations from __future__ import annotations
import warnings import warnings
from collections.abc import Generator
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import Path
from typing import Generator
import pytest import pytest

View File

@ -5,8 +5,9 @@ import os
import os.path import os.path
import tempfile import tempfile
import time import time
from collections.abc import Generator
from pathlib import Path from pathlib import Path
from typing import Any, Generator from typing import Any
import pytest import pytest

View File

@ -2,10 +2,10 @@ from __future__ import annotations
import os import os
import warnings import warnings
from collections.abc import Generator
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import Path
from types import ModuleType from types import ModuleType
from typing import Generator
import pytest import pytest

View File

@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Generator
from contextlib import contextmanager from contextlib import contextmanager
from typing import Generator
import pytest import pytest

View File

@ -4,9 +4,9 @@ Tests for resize functionality.
from __future__ import annotations from __future__ import annotations
from collections.abc import Generator
from itertools import permutations from itertools import permutations
from pathlib import Path from pathlib import Path
from typing import Generator
import pytest import pytest

View File

@ -2,7 +2,7 @@ from __future__ import annotations
import contextlib import contextlib
import os.path import os.path
from typing import Sequence from collections.abc import Sequence
import pytest import pytest

View File

@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from typing import Generator from collections.abc import Generator
import pytest import pytest

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import array import array
import math import math
import struct import struct
from typing import Sequence from collections.abc import Sequence
import pytest import pytest

View File

@ -68,8 +68,8 @@ and :pypi:`olefile` for Pillow to read FPX and MIC images::
.. tab:: Windows .. tab:: Windows
We provide Pillow binaries for Windows compiled for the matrix of supported We provide Pillow binaries for Windows compiled for the matrix of supported
Pythons in the wheel format. These include x86, x86-64 and arm64 versions Pythons in the wheel format. These include x86, x86-64 and arm64 versions.
(with the exception of Python 3.8 on arm64). These binaries include support These binaries include support
for all optional libraries except libimagequant and libxcb. Raqm support for all optional libraries except libimagequant and libxcb. Raqm support
requires FriBiDi to be installed separately:: requires FriBiDi to be installed separately::

View File

@ -1,5 +1,5 @@
Python,3.13,3.12,3.11,3.10,3.9,3.8,3.7,3.6,3.5 Python,3.13,3.12,3.11,3.10,3.9,3.8,3.7,3.6,3.5
Pillow >= 11,Yes,Yes,Yes,Yes,Yes,Yes,,, Pillow >= 11,Yes,Yes,Yes,Yes,Yes,,,,
Pillow 10.1 - 10.4,,Yes,Yes,Yes,Yes,Yes,,, Pillow 10.1 - 10.4,,Yes,Yes,Yes,Yes,Yes,,,
Pillow 10.0,,,Yes,Yes,Yes,Yes,,, Pillow 10.0,,,Yes,Yes,Yes,Yes,,,
Pillow 9.3 - 9.5,,,Yes,Yes,Yes,Yes,Yes,, Pillow 9.3 - 9.5,,,Yes,Yes,Yes,Yes,Yes,,

1 Python 3.13 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5
2 Pillow >= 11 Yes Yes Yes Yes Yes Yes
3 Pillow 10.1 - 10.4 Yes Yes Yes Yes Yes
4 Pillow 10.0 Yes Yes Yes Yes
5 Pillow 9.3 - 9.5 Yes Yes Yes Yes Yes

View File

@ -35,14 +35,12 @@ These platforms are built and tested for every change.
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Gentoo | 3.9 | x86-64 | | Gentoo | 3.9 | x86-64 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| macOS 13 Ventura | 3.8, 3.9 | x86-64 | | macOS 13 Ventura | 3.9 | x86-64 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| macOS 14 Sonoma | 3.10, 3.11, 3.12, 3.13, | arm64 | | macOS 14 Sonoma | 3.10, 3.11, 3.12, 3.13, | arm64 |
| | PyPy3 | | | | PyPy3 | |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Ubuntu Linux 20.04 LTS (Focal) | 3.8 | x86-64 | | Ubuntu Linux 22.04 LTS (Jammy) | 3.9, 3.10, 3.11, | x86-64 |
+----------------------------------+----------------------------+---------------------+
| Ubuntu Linux 22.04 LTS (Jammy) | 3.8, 3.9, 3.10, 3.11, | x86-64 |
| | 3.12, 3.13, PyPy3 | | | | 3.12, 3.13, PyPy3 | |
| +----------------------------+---------------------+ | +----------------------------+---------------------+
| | 3.10 | arm64v8 | | | 3.10 | arm64v8 |
@ -50,16 +48,16 @@ These platforms are built and tested for every change.
| Ubuntu Linux 24.04 LTS (Noble) | 3.12 | x86-64, ppc64le, | | Ubuntu Linux 24.04 LTS (Noble) | 3.12 | x86-64, ppc64le, |
| | | s390x | | | | s390x |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Windows Server 2016 | 3.8 | x86-64 | | Windows Server 2016 | 3.9 | x86-64 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+
| Windows Server 2022 | 3.8, 3.9, 3.10, 3.11, | x86-64 | | Windows Server 2022 | 3.9, 3.10, 3.11, | x86-64 |
| | 3.12, 3.13, PyPy3 | | | | 3.12, 3.13, PyPy3 | |
| +----------------------------+---------------------+ | +----------------------------+---------------------+
| | 3.12 | x86 | | | 3.12 | x86 |
| +----------------------------+---------------------+ | +----------------------------+---------------------+
| | 3.9 (MinGW) | x86-64 | | | 3.9 (MinGW) | x86-64 |
| +----------------------------+---------------------+ | +----------------------------+---------------------+
| | 3.8, 3.9 (Cygwin) | x86-64 | | | 3.9 (Cygwin) | x86-64 |
+----------------------------------+----------------------------+---------------------+ +----------------------------------+----------------------------+---------------------+

View File

@ -17,6 +17,12 @@ TODO
Backwards Incompatible Changes Backwards Incompatible Changes
============================== ==============================
Python 3.8
^^^^^^^^^^
Pillow has dropped support for Python 3.8,
which reached end-of-life in October 2024.
PSFile PSFile
^^^^^^ ^^^^^^

View File

@ -18,12 +18,11 @@ license = { text = "HPND" }
authors = [ authors = [
{ name = "Jeffrey A. Clark", email = "aclark@aclark.net" }, { name = "Jeffrey A. Clark", email = "aclark@aclark.net" },
] ]
requires-python = ">=3.8" requires-python = ">=3.9"
classifiers = [ classifiers = [
"Development Status :: 6 - Mature", "Development Status :: 6 - Mature",
"License :: OSI Approved :: Historical Permission Notice and Disclaimer (HPND)", "License :: OSI Approved :: Historical Permission Notice and Disclaimer (HPND)",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
@ -147,7 +146,7 @@ testpaths = [
] ]
[tool.mypy] [tool.mypy]
python_version = "3.8" python_version = "3.9"
pretty = true pretty = true
disallow_any_generics = true disallow_any_generics = true
enable_error_code = "ignore-without-code" enable_error_code = "ignore-without-code"

View File

@ -32,7 +32,7 @@ import subprocess
import sys import sys
from enum import IntEnum from enum import IntEnum
from functools import cached_property from functools import cached_property
from typing import IO, TYPE_CHECKING, Any, List, Literal, NamedTuple, Union from typing import IO, TYPE_CHECKING, Any, Literal, NamedTuple, Union
from . import ( from . import (
Image, Image,
@ -504,7 +504,7 @@ def _normalize_mode(im: Image.Image) -> Image.Image:
return im.convert("L") return im.convert("L")
_Palette = Union[bytes, bytearray, List[int], ImagePalette.ImagePalette] _Palette = Union[bytes, bytearray, list[int], ImagePalette.ImagePalette]
def _normalize_palette( def _normalize_palette(

View File

@ -38,7 +38,7 @@ import struct
import sys import sys
import tempfile import tempfile
import warnings import warnings
from collections.abc import Callable, MutableMapping from collections.abc import Callable, MutableMapping, Sequence
from enum import IntEnum from enum import IntEnum
from types import ModuleType from types import ModuleType
from typing import ( from typing import (
@ -47,8 +47,6 @@ from typing import (
Any, Any,
Literal, Literal,
Protocol, Protocol,
Sequence,
Tuple,
cast, cast,
) )
@ -1097,7 +1095,7 @@ class Image:
if trns is not None: if trns is not None:
try: try:
new_im.info["transparency"] = new_im.palette.getcolor( new_im.info["transparency"] = new_im.palette.getcolor(
cast(Tuple[int, ...], trns), # trns was converted to RGB cast(tuple[int, ...], trns), # trns was converted to RGB
new_im, new_im,
) )
except Exception: except Exception:
@ -3075,7 +3073,7 @@ def new(
and isinstance(color, (list, tuple)) and isinstance(color, (list, tuple))
and all(isinstance(i, int) for i in color) and all(isinstance(i, int) for i in color)
): ):
color_ints: tuple[int, ...] = cast(Tuple[int, ...], tuple(color)) color_ints: tuple[int, ...] = cast(tuple[int, ...], tuple(color))
if len(color_ints) == 3 or len(color_ints) == 4: if len(color_ints) == 3 or len(color_ints) == 4:
# RGB or RGBA value for a P image # RGB or RGBA value for a P image
from . import ImagePalette from . import ImagePalette

View File

@ -34,8 +34,9 @@ from __future__ import annotations
import math import math
import numbers import numbers
import struct import struct
from collections.abc import Sequence
from types import ModuleType from types import ModuleType
from typing import TYPE_CHECKING, AnyStr, Callable, List, Sequence, Tuple, Union, cast from typing import TYPE_CHECKING, AnyStr, Callable, Union, cast
from . import Image, ImageColor from . import Image, ImageColor
from ._deprecate import deprecate from ._deprecate import deprecate
@ -51,7 +52,7 @@ except AttributeError:
if TYPE_CHECKING: if TYPE_CHECKING:
from . import ImageDraw2, ImageFont from . import ImageDraw2, ImageFont
_Ink = Union[float, Tuple[int, ...], str] _Ink = Union[float, tuple[int, ...], str]
""" """
A simple 2D drawing interface for PIL images. A simple 2D drawing interface for PIL images.
@ -1124,7 +1125,7 @@ def _compute_regular_polygon_vertices(
msg = "bounding_circle should only contain numeric data" msg = "bounding_circle should only contain numeric data"
raise ValueError(msg) raise ValueError(msg)
*centroid, polygon_radius = cast(List[float], list(bounding_circle)) *centroid, polygon_radius = cast(list[float], list(bounding_circle))
elif len(bounding_circle) == 2 and isinstance(bounding_circle[0], (list, tuple)): elif len(bounding_circle) == 2 and isinstance(bounding_circle[0], (list, tuple)):
if not all( if not all(
isinstance(i, (int, float)) for i in bounding_circle[0] isinstance(i, (int, float)) for i in bounding_circle[0]
@ -1136,7 +1137,7 @@ def _compute_regular_polygon_vertices(
msg = "bounding_circle centre should contain 2D coordinates (e.g. (x, y))" msg = "bounding_circle centre should contain 2D coordinates (e.g. (x, y))"
raise ValueError(msg) raise ValueError(msg)
centroid = cast(List[float], list(bounding_circle[0])) centroid = cast(list[float], list(bounding_circle[0]))
polygon_radius = cast(float, bounding_circle[1]) polygon_radius = cast(float, bounding_circle[1])
else: else:
msg = ( msg = (

View File

@ -18,8 +18,9 @@ from __future__ import annotations
import abc import abc
import functools import functools
from collections.abc import Sequence
from types import ModuleType from types import ModuleType
from typing import TYPE_CHECKING, Any, Callable, Sequence, cast from typing import TYPE_CHECKING, Any, Callable, cast
if TYPE_CHECKING: if TYPE_CHECKING:
from . import _imaging from . import _imaging

View File

@ -21,7 +21,8 @@ from __future__ import annotations
import functools import functools
import operator import operator
import re import re
from typing import Protocol, Sequence, cast from collections.abc import Sequence
from typing import Protocol, cast
from . import ExifTags, Image, ImagePalette from . import ExifTags, Image, ImagePalette

View File

@ -18,7 +18,8 @@
from __future__ import annotations from __future__ import annotations
import array import array
from typing import IO, TYPE_CHECKING, Sequence from collections.abc import Sequence
from typing import IO, TYPE_CHECKING
from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile

View File

@ -14,7 +14,8 @@
# #
from __future__ import annotations from __future__ import annotations
from typing import Any, Sequence from collections.abc import Sequence
from typing import Any
from . import Image from . import Image

View File

@ -16,8 +16,8 @@
# #
from __future__ import annotations from __future__ import annotations
from collections.abc import Sequence
from io import BytesIO from io import BytesIO
from typing import Sequence
from . import Image, ImageFile from . import Image, ImageFile
from ._binary import i16be as i16 from ._binary import i16be as i16

View File

@ -18,7 +18,7 @@ from __future__ import annotations
import io import io
import os import os
import struct import struct
from typing import IO, Tuple, cast from typing import IO, cast
from . import Image, ImageFile, ImagePalette, _binary from . import Image, ImageFile, ImagePalette, _binary
@ -82,7 +82,7 @@ class BoxReader:
self.remaining_in_box = -1 self.remaining_in_box = -1
# Read the length and type of the next box # Read the length and type of the next box
lbox, tbox = cast(Tuple[int, bytes], self.read_fields(">I4s")) lbox, tbox = cast(tuple[int, bytes], self.read_fields(">I4s"))
if lbox == 1: if lbox == 1:
lbox = cast(int, self.read_fields(">Q")[0]) lbox = cast(int, self.read_fields(">Q")[0])
hlen = 16 hlen = 16

View File

@ -8,7 +8,7 @@ import os
import re import re
import time import time
import zlib import zlib
from typing import TYPE_CHECKING, Any, List, NamedTuple, Union from typing import TYPE_CHECKING, Any, NamedTuple, Union
# see 7.9.2.2 Text String Type on page 86 and D.3 PDFDocEncoding Character Set # see 7.9.2.2 Text String Type on page 86 and D.3 PDFDocEncoding Character Set
@ -240,7 +240,7 @@ class PdfName:
return bytes(result) return bytes(result)
class PdfArray(List[Any]): class PdfArray(list[Any]):
def __bytes__(self) -> bytes: def __bytes__(self) -> bytes:
return b"[ " + b" ".join(pdf_repr(x) for x in self) + b" ]" return b"[ " + b" ".join(pdf_repr(x) for x in self) + b" ]"

View File

@ -37,7 +37,7 @@ from __future__ import annotations
import os import os
import struct import struct
import sys import sys
from typing import IO, TYPE_CHECKING, Any, Tuple, cast from typing import IO, TYPE_CHECKING, Any, cast
from . import Image, ImageFile from . import Image, ImageFile
@ -187,7 +187,7 @@ class SpiderImageFile(ImageFile.ImageFile):
def convert2byte(self, depth: int = 255) -> Image.Image: def convert2byte(self, depth: int = 255) -> Image.Image:
extrema = self.getextrema() extrema = self.getextrema()
assert isinstance(extrema[0], float) assert isinstance(extrema[0], float)
minimum, maximum = cast(Tuple[float, float], extrema) minimum, maximum = cast(tuple[float, float], extrema)
m: float = 1 m: float = 1
if maximum != minimum: if maximum != minimum:
m = depth / (maximum - minimum) m = depth / (maximum - minimum)

View File

@ -2,7 +2,8 @@ from __future__ import annotations
import os import os
import sys import sys
from typing import TYPE_CHECKING, Any, Protocol, Sequence, TypeVar, Union from collections.abc import Sequence
from typing import TYPE_CHECKING, Any, Protocol, TypeVar, Union
if TYPE_CHECKING: if TYPE_CHECKING:
try: try:

View File

@ -3,7 +3,7 @@ requires =
tox>=4.2 tox>=4.2
env_list = env_list =
lint lint
py{py3, 313, 312, 311, 310, 39, 38} py{py3, 313, 312, 311, 310, 39}
[testenv] [testenv]
deps = deps =

View File

@ -16,7 +16,7 @@ For more extensive info, see the [Windows build instructions](build.rst).
The following is a simplified version of the script used on AppVeyor: The following is a simplified version of the script used on AppVeyor:
``` ```
set PYTHON=C:\Python38\bin set PYTHON=C:\Python39\bin
cd /D C:\Pillow\winbuild cd /D C:\Pillow\winbuild
%PYTHON%\python.exe build_prepare.py -v --depends=C:\pillow-depends %PYTHON%\python.exe build_prepare.py -v --depends=C:\pillow-depends
build\build_dep_all.cmd build\build_dep_all.cmd

View File

@ -114,7 +114,7 @@ Example
The following is a simplified version of the script used on AppVeyor:: The following is a simplified version of the script used on AppVeyor::
set PYTHON=C:\Python38\bin set PYTHON=C:\Python39\bin
cd /D C:\Pillow\winbuild cd /D C:\Pillow\winbuild
%PYTHON%\python.exe build_prepare.py -v --depends C:\pillow-depends %PYTHON%\python.exe build_prepare.py -v --depends C:\pillow-depends
build\build_dep_all.cmd build\build_dep_all.cmd