From eb76f0afd8313f8568cec6a02725ef61ee54a8f7 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:19:41 +0300 Subject: [PATCH 1/6] Replace hasattr(sys, "pypy_version_info") with sys.implementation.name == "pypy" --- src/PIL/Image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index ddbaec20a05..3493df1e467 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -708,7 +708,7 @@ def close(self) -> None: more information. """ if getattr(self, "map", None): - if sys.platform == "win32" and hasattr(sys, "pypy_version_info"): + if sys.platform == "win32" and sys.implementation.name == "pypy": self.map.close() self.map: mmap.mmap | None = None From 46115e503a10005f007469b135cdd18bfa6b61a1 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:35:54 +0300 Subject: [PATCH 2/6] Replace functools.reduce with sum --- src/PIL/ImageFilter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index 428ceb1aaa9..ffdb7ffca10 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -17,7 +17,6 @@ from __future__ import annotations import abc -import functools from collections.abc import Sequence from typing import cast @@ -79,7 +78,7 @@ def __init__( ) -> None: if scale is None: # default scale is sum of kernel - scale = functools.reduce(lambda a, b: a + b, kernel) + scale = sum(kernel) if size[0] * size[1] != len(kernel): msg = "not enough coefficients in kernel" raise ValueError(msg) From 9bc5944dcf7b0f30c05358ad00e364a491b6bc56 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:39:36 +0300 Subject: [PATCH 3/6] Replace functools.reduce and operator.add with sum --- src/PIL/ImageOps.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index cdec4d5dc7d..0b222e7f22f 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -18,8 +18,6 @@ # from __future__ import annotations -import functools -import operator import re from collections.abc import Sequence from typing import Literal, Protocol, cast, overload @@ -494,7 +492,7 @@ def equalize(image: Image.Image, mask: Image.Image | None = None) -> Image.Image if len(histo) <= 1: lut.extend(list(range(256))) else: - step = (functools.reduce(operator.add, histo) - histo[-1]) // 255 + step = (sum(histo) - histo[-1]) // 255 if not step: lut.extend(list(range(256))) else: From 19ccee8d56029417f0f5b1dc919541a1b4790f63 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:40:16 +0300 Subject: [PATCH 4/6] Replace loop with sum --- src/PIL/ImageOps.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 0b222e7f22f..fea9d1258bf 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -118,9 +118,7 @@ def autocontrast( if not isinstance(cutoff, tuple): cutoff = (cutoff, cutoff) # get number of pixels - n = 0 - for ix in range(256): - n = n + h[ix] + n = sum(h) # remove cutoff% pixels from the low end cut = int(n * cutoff[0] // 100) for lo in range(256): From 7098c84cf12479b2d784a6d5aa4610bbb89d17e7 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:51:05 +0300 Subject: [PATCH 5/6] Replace int(color[i:j], 16) slices with bytes.fromhex() --- src/PIL/ImageColor.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/PIL/ImageColor.py b/src/PIL/ImageColor.py index ef1548c7e23..c2a84100f54 100644 --- a/src/PIL/ImageColor.py +++ b/src/PIL/ImageColor.py @@ -62,15 +62,12 @@ def getrgb(color: str) -> tuple[int, int, int] | tuple[int, int, int, int]: ) if re.match("#[a-f0-9]{6}$", color): - return int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16) + r, g, b = bytes.fromhex(color[1:]) + return r, g, b if re.match("#[a-f0-9]{8}$", color): - return ( - int(color[1:3], 16), - int(color[3:5], 16), - int(color[5:7], 16), - int(color[7:9], 16), - ) + r, g, b, a = bytes.fromhex(color[1:]) + return r, g, b, a m = re.match(r"rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) if m: From 43993e93ba28fcd627ba579c37d9bf281e3c8bd3 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 9 Aug 2026 16:02:21 +0300 Subject: [PATCH 6/6] Simplify dict key sorting --- src/PIL/PdfParser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 5ba70ba209d..132b6ac8b78 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -177,7 +177,7 @@ def keys(self) -> set[int]: def write(self, f: IO[bytes]) -> int: keys = sorted(set(self.new_entries.keys()) | set(self.deleted_entries.keys())) - deleted_keys = sorted(set(self.deleted_entries.keys())) + deleted_keys = sorted(self.deleted_entries) startxref = f.tell() f.write(b"xref\n") while keys: