From 065b74e13bc8445c4a4b612cfef60de036c0ca72 Mon Sep 17 00:00:00 2001 From: Ben Konrath Date: Sun, 20 Oct 2024 10:45:22 +0200 Subject: [PATCH] Add support for Python 3.13 --- easy_thumbnails/optimize/post_processor.py | 27 +++++++++++++++++++--- setup.py | 1 + tox.ini | 3 ++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/easy_thumbnails/optimize/post_processor.py b/easy_thumbnails/optimize/post_processor.py index 4f8c8edd..63259c2f 100644 --- a/easy_thumbnails/optimize/post_processor.py +++ b/easy_thumbnails/optimize/post_processor.py @@ -1,6 +1,6 @@ import logging import subprocess -from imghdr import what as determinetype +from PIL import Image, UnidentifiedImageError from django.core.files.base import ContentFile from django.core.files.temp import NamedTemporaryFile from easy_thumbnails.optimize.conf import settings @@ -35,9 +35,30 @@ def check_output(*popenargs, **kwargs): def optimize_thumbnail(thumbnail): '''Optimize thumbnail images by removing unnecessary data''' + # Ignore remote storage backends. try: - optimize_command = settings.THUMBNAIL_OPTIMIZE_COMMAND[ - determinetype(thumbnail.path)] + thumbnail_path = thumbnail.path + except NotImplementedError: + return + + # We can't use thumbnail.image.format directly because it's set to `None` for images + # that have been created by running a method on an existing image. i.e. It's `None` + # because of the thumnailing operations. + # https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.format + # + # Image.open() is lazy and the full file will not be read when determining the + # format. + # https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.open + try: + with Image.open(thumbnail_path) as img: + # Use the lower case version of format to match the output of previously used + # imghdr.what() (removed in Python 3.13). + format = img.format.lower() + except UnidentifiedImageError: + return + + try: + optimize_command = settings.THUMBNAIL_OPTIMIZE_COMMAND[format] if not optimize_command: return except (TypeError, KeyError, NotImplementedError): diff --git a/setup.py b/setup.py index 849b1bb6..4cda6d39 100644 --- a/setup.py +++ b/setup.py @@ -58,6 +58,7 @@ def read_files(*filenames): "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", ], diff --git a/tox.ini b/tox.ini index cc5ac937..c8446b06 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ distribute = False envlist = py{38,39,310,311,312}-django42{-svg,} py{310,311,312}-django50{-svg,} - py{310,311,312}-django51{-svg,} + py{310,311,312,313}-django51{-svg,} skip_missing_interpreters = True [gh-actions] @@ -12,6 +12,7 @@ python = 3.10: py310 3.11: py311 3.12: py312 + 3.13: py313 [testenv] setenv =