From 6be0c7a26c81b0df722323ddb776508b834dd7d3 Mon Sep 17 00:00:00 2001 From: Matthias Meulien Date: Tue, 27 Aug 2024 16:46:02 +0200 Subject: [PATCH] Fix tests warning about imghdr being deprecated --- mopidy_local/storage.py | 37 +++++++++++++++++++++++++------------ tests/dummy_audio.py | 1 - tests/test_storage.py | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/mopidy_local/storage.py b/mopidy_local/storage.py index 134b8a7..7f2d232 100644 --- a/mopidy_local/storage.py +++ b/mopidy_local/storage.py @@ -1,5 +1,4 @@ import hashlib -import imghdr import logging import pathlib import shutil @@ -21,7 +20,6 @@ def check_dirs_and_files(config): ) -# would be nice to have these in imghdr... def get_image_size_png(data): return struct.unpack(">ii", data[16:24]) @@ -58,13 +56,25 @@ def get_image_size_jpeg(data): return width, height -def test_jpeg(data, file_handle): - # Additional JPEG detection looking for JPEG SOI marker - if data[:2] == b"\xff\xd8": - return "jpeg" +MIN_BYTES_FOR_IMAGE_TYPE = 8 + + +def get_image_type_from_header(header: bytes) -> str: + # original source: https://github.com/sphinx-doc/sphinx/commit/a502e7 + if len(header) < MIN_BYTES_FOR_IMAGE_TYPE: + raise ValueError("Unknown image type") -imghdr.tests.append(test_jpeg) + if header.startswith(b"\x89PNG\r\n\x1A\n"): + return "png" + + if header.startswith((b"GIF87a", b"GIF89a")): + return "gif" + + if header.startswith(b"\xFF\xD8"): + return "jpeg" + + raise ValueError("Unknown image type") class LocalStorageProvider: @@ -214,15 +224,18 @@ def _extract_images(self, uri, tags): return images def _get_or_create_image_file(self, path, data=None): - what = imghdr.what(path, data) - if not what: - raise ValueError("Unknown image type") if not data: - data_source = path.as_uri() with open(path, "rb") as f: - data = f.read() + header = f.read(MIN_BYTES_FOR_IMAGE_TYPE) + + what = get_image_type_from_header(header) + data_source = path.as_uri() + data = header + f.read() else: + header = data[:MIN_BYTES_FOR_IMAGE_TYPE] + what = get_image_type_from_header(header) data_source = "embedded image" + digest, width, height = hashlib.md5(data).hexdigest(), None, None try: if what == "png": diff --git a/tests/dummy_audio.py b/tests/dummy_audio.py index 14acbbd..5f703eb 100644 --- a/tests/dummy_audio.py +++ b/tests/dummy_audio.py @@ -4,7 +4,6 @@ tests of the core and backends. """ - import pykka from mopidy import audio diff --git a/tests/test_storage.py b/tests/test_storage.py index 6caed2c..0cd7e41 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -3,6 +3,23 @@ from mopidy_local import storage +def test_get_image_type_from_header_png(): + data_bytes = b"\x89PNG\r\n\x1A\nffe000104a464" + assert storage.get_image_type_from_header(data_bytes) == "png" + + +@pytest.mark.parametrize( + "data", + [ + pytest.param("474946383761ffe000104a46", id="GIF87a"), + pytest.param("474946383961ffe000104a46", id="GIF89a"), + ], +) +def test_get_image_type_from_header_gif(data): + data_bytes = bytes.fromhex(data) + assert storage.get_image_type_from_header(data_bytes) == "gif" + + @pytest.mark.parametrize( "data", [ @@ -11,6 +28,18 @@ pytest.param("ffd8ffe1095068747470", id="XMP"), ], ) -def test_jpeg_detection(data): +def test_get_image_type_from_header_jpeg(data): data_bytes = bytes.fromhex(data) - assert storage.imghdr.what(None, data_bytes) is not None + assert storage.get_image_type_from_header(data_bytes) == "jpeg" + + +def test_get_image_type_from_header_unknown_header(): + data_bytes = b"PIF81affe000104a464" + with pytest.raises(ValueError): + storage.get_image_type_from_header(data_bytes) + + +def test_get_image_type_from_header_too_short_header(): + data_bytes = b"\xFF" + with pytest.raises(ValueError): + storage.get_image_type_from_header(data_bytes)