|
11 | 11 | import sys
|
12 | 12 | import sysconfig
|
13 | 13 | import tempfile
|
| 14 | +from functools import lru_cache |
14 | 15 | from io import BytesIO
|
15 | 16 | from typing import Any, Callable, Sequence
|
16 | 17 |
|
@@ -250,23 +251,27 @@ def tostring(im: Image.Image, string_format: str, **options: Any) -> bytes:
|
250 | 251 | return out.getvalue()
|
251 | 252 |
|
252 | 253 |
|
253 |
| -def hopper(mode: str | None = None, cache: dict[str, Image.Image] = {}) -> Image.Image: |
| 254 | +def hopper(mode: str | None = None) -> Image.Image: |
| 255 | + # Use caching to reduce reading from disk, but return a copy |
| 256 | + # so that the cached image isn't modified by the tests |
| 257 | + # (for fast, isolated, repeatable tests). |
| 258 | + |
254 | 259 | if mode is None:
|
255 | 260 | # Always return fresh not-yet-loaded version of image.
|
256 |
| - # Operations on not-yet-loaded images is separate class of errors |
257 |
| - # what we should catch. |
| 261 | + # Operations on not-yet-loaded images are a separate class of errors |
| 262 | + # that we should catch. |
258 | 263 | return Image.open("Tests/images/hopper.ppm")
|
259 |
| - # Use caching to reduce reading from disk but so an original copy is |
260 |
| - # returned each time and the cached image isn't modified by tests |
261 |
| - # (for fast, isolated, repeatable tests). |
262 |
| - im = cache.get(mode) |
263 |
| - if im is None: |
264 |
| - if mode == "F": |
265 |
| - im = hopper("L").convert(mode) |
266 |
| - else: |
267 |
| - im = hopper().convert(mode) |
268 |
| - cache[mode] = im |
269 |
| - return im.copy() |
| 264 | + |
| 265 | + return _cached_hopper(mode).copy() |
| 266 | + |
| 267 | + |
| 268 | +@lru_cache |
| 269 | +def _cached_hopper(mode: str) -> Image.Image: |
| 270 | + if mode == "F": |
| 271 | + im = hopper("L") |
| 272 | + else: |
| 273 | + im = hopper() |
| 274 | + return im.convert(mode) |
270 | 275 |
|
271 | 276 |
|
272 | 277 | def djpeg_available() -> bool:
|
|
0 commit comments