diff --git a/.github/workflows/system-info.py b/.github/workflows/system-info.py index 57f28c620b7..9e97b897104 100644 --- a/.github/workflows/system-info.py +++ b/.github/workflows/system-info.py @@ -6,6 +6,7 @@ Requested here: https://github.com/actions/virtual-environments/issues/79 """ + from __future__ import annotations import os diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5ce0c9a1792..c52fdcb552d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,17 +1,17 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.9 + rev: v0.2.0 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.12.1 + rev: 24.1.1 hooks: - id: black - repo: https://github.com/PyCQA/bandit - rev: 1.7.6 + rev: 1.7.7 hooks: - id: bandit args: [--severity-level=high] @@ -48,12 +48,12 @@ repos: - id: sphinx-lint - repo: https://github.com/tox-dev/pyproject-fmt - rev: 1.5.3 + rev: 1.7.0 hooks: - id: pyproject-fmt - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.15 + rev: v0.16 hooks: - id: validate-pyproject diff --git a/Tests/helper.py b/Tests/helper.py index b2e7d43dd67..3e2a40e02da 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -1,6 +1,7 @@ """ Helper functions. """ + from __future__ import annotations import logging diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index 09ee8986aca..b78a0dd8109 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -1,4 +1,5 @@ """Test DdsImagePlugin""" + from __future__ import annotations from io import BytesIO diff --git a/Tests/test_file_libtiff_small.py b/Tests/test_file_libtiff_small.py index ac5270eac30..617e1e89c72 100644 --- a/Tests/test_file_libtiff_small.py +++ b/Tests/test_file_libtiff_small.py @@ -9,7 +9,6 @@ class TestFileLibTiffSmall(LibTiffTestCase): - """The small lena image was failing on open in the libtiff decoder because the file pointer was set to the wrong place by a spurious seek. It wasn't failing with the byteio method. diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 00cd4e7a9a1..e4cb2dad102 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -230,9 +230,7 @@ def test_list(self) -> None: assert im.getpixel([0, 0]) == (20, 20, 70) @pytest.mark.parametrize("mode", ("I;16", "I;16B")) - @pytest.mark.parametrize( - "expected_color", (2**15 - 1, 2**15, 2**15 + 1, 2**16 - 1) - ) + @pytest.mark.parametrize("expected_color", (2**15 - 1, 2**15, 2**15 + 1, 2**16 - 1)) def test_signedness(self, mode, expected_color) -> None: # see https://github.com/python-pillow/Pillow/issues/452 # pixelaccess is using signed int* instead of uint* diff --git a/Tests/test_image_resize.py b/Tests/test_image_resize.py index bd45ee893ad..a64e4a84621 100644 --- a/Tests/test_image_resize.py +++ b/Tests/test_image_resize.py @@ -1,6 +1,7 @@ """ Tests for resize functionality. """ + from __future__ import annotations from itertools import permutations diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py index 7f652715566..83fc38ed3fd 100644 --- a/Tests/test_imagecms.py +++ b/Tests/test_imagecms.py @@ -342,9 +342,11 @@ def assert_truncated_tuple_equal(tup1, tup2, digits: int = 10) -> None: def truncate_tuple(tuple_or_float): return tuple( - truncate_tuple(val) - if isinstance(val, tuple) - else int(val * power) / power + ( + truncate_tuple(val) + if isinstance(val, tuple) + else int(val * power) / power + ) for val in tuple_or_float ) diff --git a/docs/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index e98bb86806f..2a2a0ba2961 100644 --- a/docs/example/DdsImagePlugin.py +++ b/docs/example/DdsImagePlugin.py @@ -9,6 +9,7 @@ Full text of the CC0 license: https://creativecommons.org/publicdomain/zero/1.0/ """ + from __future__ import annotations import struct diff --git a/pyproject.toml b/pyproject.toml index b1ce9cf1d07..652ae36333c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,7 +96,7 @@ config-settings = "raqm=enable raqm=vendor fribidi=vendor imagequant=disable" test-command = "cd {project} && .github/workflows/wheels-test.sh" test-extras = "tests" -[tool.ruff] +[tool.ruff.lint] select = [ "C4", # flake8-comprehensions "E", # pycodestyle errors @@ -104,25 +104,25 @@ select = [ "F", # pyflakes errors "I", # isort "ISC", # flake8-implicit-str-concat + "LOG", # flake8-logging "PGH", # pygrep-hooks "RUF100", # unused noqa (yesqa) "UP", # pyupgrade "W", # pycodestyle warnings "YTT", # flake8-2020 - # "LOG", # TODO: enable flake8-logging when it's not in preview anymore ] -extend-ignore = [ +ignore = [ "E203", # Whitespace before ':' "E221", # Multiple spaces before operator "E226", # Missing whitespace around arithmetic operator "E241", # Multiple spaces after ',' ] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "Tests/oss-fuzz/fuzz_font.py" = ["I002"] "Tests/oss-fuzz/fuzz_pillow.py" = ["I002"] -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party = ["PIL"] required-imports = ["from __future__ import annotations"] diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index b8f38b78a2e..f0fbc8cc28a 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -28,6 +28,7 @@ - DXT3 compression is used if alpha_encoding == 1. - DXT5 compression is used if alpha_encoding == 7. """ + from __future__ import annotations import os diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index eb4c8f557af..3785174ef65 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -9,6 +9,7 @@ Full text of the CC0 license: https://creativecommons.org/publicdomain/zero/1.0/ """ + from __future__ import annotations import io diff --git a/src/PIL/FontFile.py b/src/PIL/FontFile.py index 3ec1ae819fc..1e0c1c166b5 100644 --- a/src/PIL/FontFile.py +++ b/src/PIL/FontFile.py @@ -50,9 +50,7 @@ def __init__(self) -> None: | None ] = [None] * 256 - def __getitem__( - self, ix: int - ) -> ( + def __getitem__(self, ix: int) -> ( tuple[ tuple[int, int], tuple[int, int, int, int], diff --git a/src/PIL/FtexImagePlugin.py b/src/PIL/FtexImagePlugin.py index d5513a56a11..b4488e6ee9c 100644 --- a/src/PIL/FtexImagePlugin.py +++ b/src/PIL/FtexImagePlugin.py @@ -50,6 +50,7 @@ Note: All data is stored in little-Endian (Intel) byte order. """ + from __future__ import annotations import struct diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 57d87078bca..dc842d7a30b 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -641,9 +641,9 @@ def _write_multiple_frames(im, fp, palette): if encoderinfo.get("optimize") and im_frame.mode != "1": if "transparency" not in encoderinfo: try: - encoderinfo[ - "transparency" - ] = im_frame.palette._new_color_index(im_frame) + encoderinfo["transparency"] = ( + im_frame.palette._new_color_index(im_frame) + ) except ValueError: pass if "transparency" in encoderinfo: diff --git a/src/PIL/ImageCms.py b/src/PIL/ImageCms.py index 3e40105e46a..2b0ed6c9d2f 100644 --- a/src/PIL/ImageCms.py +++ b/src/PIL/ImageCms.py @@ -281,7 +281,6 @@ def tobytes(self): class ImageCmsTransform(Image.ImagePointHandler): - """ Transform. This can be used with the procedural API, or with the standard :py:func:`~PIL.Image.Image.point` method. @@ -369,7 +368,6 @@ def get_display_profile(handle=None): class PyCMSError(Exception): - """(pyCMS) Exception class. This is used for all errors in the pyCMS API.""" diff --git a/src/PIL/JpegPresets.py b/src/PIL/JpegPresets.py index 9ecfdb2599a..d0e64a35ee1 100644 --- a/src/PIL/JpegPresets.py +++ b/src/PIL/JpegPresets.py @@ -62,6 +62,7 @@ https://web.archive.org/web/20120328125543/http://www.jpegcameras.com/libjpeg/libjpeg-3.html """ + from __future__ import annotations # fmt: off diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index 3506aadce83..1777f1f20db 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -188,9 +188,9 @@ def _save(im, fp, filename, save_all=False): x_resolution = y_resolution = im.encoderinfo.get("resolution", 72.0) info = { - "title": None - if is_appending - else os.path.splitext(os.path.basename(filename))[0], + "title": ( + None if is_appending else os.path.splitext(os.path.basename(filename))[0] + ), "author": None, "subject": None, "keywords": None, diff --git a/src/PIL/__init__.py b/src/PIL/__init__.py index 3fcac8643cb..63a45769ba6 100644 --- a/src/PIL/__init__.py +++ b/src/PIL/__init__.py @@ -12,6 +12,7 @@ ;-) """ + from __future__ import annotations from . import _version diff --git a/src/PIL/_tkinter_finder.py b/src/PIL/_tkinter_finder.py index 03a6eba44ff..71c0ad4651b 100644 --- a/src/PIL/_tkinter_finder.py +++ b/src/PIL/_tkinter_finder.py @@ -1,5 +1,6 @@ """ Find compiled module linking to Tcl / Tk libraries """ + from __future__ import annotations import sys