From 504a2e17c85221c48a81b8198b859d169e8908a8 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 20 Mar 2024 09:49:18 +0200 Subject: [PATCH 1/5] Use functools.lru_cache for hopper() --- Tests/helper.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 9849bf65565..dacce3fb948 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -11,6 +11,7 @@ import sys import sysconfig import tempfile +from functools import lru_cache from io import BytesIO from typing import Any, Callable, Sequence @@ -250,25 +251,27 @@ def tostring(im: Image.Image, string_format: str, **options: Any) -> bytes: return out.getvalue() -def hopper(mode: str | None = None, cache: dict[str, Image.Image] = {}) -> Image.Image: +def hopper(mode: str | None = None) -> Image.Image: + # Use caching to reduce reading from disk but so an original copy is + # returned each time and the cached image isn't modified by tests + # (for fast, isolated, repeatable tests). + return _cached_hopper(mode).copy() + + +@lru_cache(maxsize=None) +def _cached_hopper(mode: str | None = None) -> Image.Image: if mode is None: # Always return fresh not-yet-loaded version of image. # Operations on not-yet-loaded images is separate class of errors # what we should catch. return Image.open("Tests/images/hopper.ppm") - # Use caching to reduce reading from disk but so an original copy is - # returned each time and the cached image isn't modified by tests - # (for fast, isolated, repeatable tests). - im = cache.get(mode) - if im is None: - if mode == "F": - im = hopper("L").convert(mode) - elif mode[:4] == "I;16": - im = hopper("I").convert(mode) - else: - im = hopper().convert(mode) - cache[mode] = im - return im.copy() + if mode == "F": + im = _cached_hopper("L").convert(mode) + elif mode[:4] == "I;16": + im = _cached_hopper("I").convert(mode) + else: + im = _cached_hopper().convert(mode) + return im def djpeg_available() -> bool: From d131f1c513d7c46017f1ab159ac8e371d609f5b4 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Thu, 28 Mar 2024 22:13:09 +0200 Subject: [PATCH 2/5] Clarify comments --- Tests/helper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index dacce3fb948..8baaf4c428b 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -252,8 +252,8 @@ def tostring(im: Image.Image, string_format: str, **options: Any) -> bytes: def hopper(mode: str | None = None) -> Image.Image: - # Use caching to reduce reading from disk but so an original copy is - # returned each time and the cached image isn't modified by tests + # Use caching to reduce reading from disk, but return a copy + # so that the cached image isn't modified by the tests # (for fast, isolated, repeatable tests). return _cached_hopper(mode).copy() From ed5cd18d9cbcb03494cfc1e90b264e35987c569a Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 31 Mar 2024 15:07:15 +0300 Subject: [PATCH 3/5] Always return fresh not-yet-loaded image for hopper(None) --- Tests/helper.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 2ce9bdfafcd..aa6fa2ba12d 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -255,20 +255,22 @@ def hopper(mode: str | None = None) -> Image.Image: # Use caching to reduce reading from disk, but return a copy # so that the cached image isn't modified by the tests # (for fast, isolated, repeatable tests). - return _cached_hopper(mode).copy() - -@lru_cache(maxsize=None) -def _cached_hopper(mode: str | None = None) -> Image.Image: if mode is None: # Always return fresh not-yet-loaded version of image. # Operations on not-yet-loaded images is separate class of errors # what we should catch. return Image.open("Tests/images/hopper.ppm") + + return _cached_hopper(mode).copy() + + +@lru_cache(maxsize=None) +def _cached_hopper(mode: str | None = None) -> Image.Image: if mode == "F": - im = _cached_hopper("L").convert(mode) + im = hopper("L").convert(mode) else: - im = _cached_hopper().convert(mode) + im = hopper().convert(mode) return im From 9f5d6e0c3136ed71fca08f7574b26541f226b60b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 31 Mar 2024 10:02:23 -0600 Subject: [PATCH 4/5] Fix type hint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondrej Baranovič --- Tests/helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/helper.py b/Tests/helper.py index aa6fa2ba12d..863bd87cfcb 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -266,7 +266,7 @@ def hopper(mode: str | None = None) -> Image.Image: @lru_cache(maxsize=None) -def _cached_hopper(mode: str | None = None) -> Image.Image: +def _cached_hopper(mode: str = None) -> Image.Image: if mode == "F": im = hopper("L").convert(mode) else: From 512ee3ff9b25cdc74ab7ab3dc6ff96f65c160aca Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:13:30 -0600 Subject: [PATCH 5/5] Simplify code and update comments Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- Tests/helper.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 863bd87cfcb..5d477144d2f 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -258,20 +258,20 @@ def hopper(mode: str | None = None) -> Image.Image: if mode is None: # Always return fresh not-yet-loaded version of image. - # Operations on not-yet-loaded images is separate class of errors - # what we should catch. + # Operations on not-yet-loaded images are a separate class of errors + # that we should catch. return Image.open("Tests/images/hopper.ppm") return _cached_hopper(mode).copy() -@lru_cache(maxsize=None) -def _cached_hopper(mode: str = None) -> Image.Image: +@lru_cache +def _cached_hopper(mode: str) -> Image.Image: if mode == "F": - im = hopper("L").convert(mode) + im = hopper("L") else: - im = hopper().convert(mode) - return im + im = hopper() + return im.convert(mode) def djpeg_available() -> bool: