From 49da9728a69ae8a63af8a4630fccc55c10e66392 Mon Sep 17 00:00:00 2001 From: Thomas Scholtes Date: Fri, 8 Mar 2024 12:17:43 +0100 Subject: [PATCH 1/3] Replace deprecated `imghdr` package with `filetype` The `imghdr` package from the Python standard library is [deprecated and will be removed in Python 3.13][1]. The deprecated PEP suggests packages filetype, puremagic, python-magic as replacements. I chose filetype because it has a [larger user-base][2] than puremagic and does not have a C dependency, like python-magic. [1]: https://peps.python.org/pep-0594/#deprecated-modules [2]: https://libraries.io/pypi/filetype --- mediafile.py | 45 +++------------------------------ pyproject.toml | 1 + test/rsrc/only-magic-bytes.jpg | Bin 622 -> 0 bytes test/test_mediafile_edge.py | 11 -------- 4 files changed, 4 insertions(+), 53 deletions(-) delete mode 100644 test/rsrc/only-magic-bytes.jpg diff --git a/mediafile.py b/mediafile.py index 5f488d7..5600c49 100644 --- a/mediafile.py +++ b/mediafile.py @@ -46,8 +46,8 @@ import codecs import datetime import enum +import filetype import functools -import imghdr import logging import math import os @@ -78,8 +78,6 @@ 'wav': 'WAVE', } -PREFERRED_IMAGE_EXTENSIONS = {'jpeg': 'jpg'} - # Exceptions. @@ -346,52 +344,15 @@ def _sc_encode(gain, peak): # Cover art and other images. -def _imghdr_what_wrapper(data): - """A wrapper around imghdr.what to account for jpeg files that can only be - identified as such using their magic bytes - See #1545 - See https://github.com/file/file/blob/master/magic/Magdir/jpeg#L12 - """ - # imghdr.what returns none for jpegs with only the magic bytes, so - # _wider_test_jpeg is run in that case. It still returns None if it didn't - # match such a jpeg file. - return imghdr.what(None, h=data) or _wider_test_jpeg(data) - - -def _wider_test_jpeg(data): - """Test for a jpeg file following the UNIX file implementation which - uses the magic bytes rather than just looking for the bytes that - represent 'JFIF' or 'EXIF' at a fixed position. - """ - if data[:2] == b'\xff\xd8': - return 'jpeg' - def image_mime_type(data): """Return the MIME type of the image data (a bytestring). """ - # This checks for a jpeg file with only the magic bytes (unrecognized by - # imghdr.what). imghdr.what returns none for that type of file, so - # _wider_test_jpeg is run in that case. It still returns None if it didn't - # match such a jpeg file. - kind = _imghdr_what_wrapper(data) - if kind in ['gif', 'jpeg', 'png', 'tiff', 'bmp']: - return 'image/{0}'.format(kind) - elif kind == 'pgm': - return 'image/x-portable-graymap' - elif kind == 'pbm': - return 'image/x-portable-bitmap' - elif kind == 'ppm': - return 'image/x-portable-pixmap' - elif kind == 'xbm': - return 'image/x-xbitmap' - else: - return 'image/x-{0}'.format(kind) + return filetype.guess_mime(data) def image_extension(data): - ext = _imghdr_what_wrapper(data) - return PREFERRED_IMAGE_EXTENSIONS.get(ext, ext) + return filetype.guess_extension(data) class ImageType(enum.Enum): diff --git a/pyproject.toml b/pyproject.toml index f558885..1f08159 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ home-page = "https://github.com/beetbox/mediafile" description-file = "README.rst" requires = [ "mutagen>=1.46", + "filetype>=1.2.0", ] requires-python = ">=3.7" classifiers = [ diff --git a/test/rsrc/only-magic-bytes.jpg b/test/rsrc/only-magic-bytes.jpg deleted file mode 100644 index ca0cf220fd40788729bd33b867ff33ae84706a3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 622 zcmex=(iUwW$pkka<)WpdpCN3cY31zV>gMj@ z=@lFj8WtWA8I_!pnwFlCnN?g;T2@|BS=HRq+ScCD*)?hMl&RCE&zL!D(c&dbmn~nh za@D5ITefc7zGLUELx+zXJ$C%W$y1juU%7hi`i+~n9zJ^f Date: Sun, 3 Nov 2024 17:50:18 +0000 Subject: [PATCH 2/3] Use "tiff" extension for TIFF files to match imghdr --- mediafile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mediafile.py b/mediafile.py index 5600c49..8a8e835 100644 --- a/mediafile.py +++ b/mediafile.py @@ -352,7 +352,9 @@ def image_mime_type(data): def image_extension(data): - return filetype.guess_extension(data) + ext = filetype.guess_extension(data) + # imghdr returned "tiff", so we should keep returning it with filetype. + return ext if ext != 'tif' else 'tiff' class ImageType(enum.Enum): From 182f3dd9f28dda8be5499c82badf8cc3bbc4fc64 Mon Sep 17 00:00:00 2001 From: Jack Wilsdon Date: Sun, 3 Nov 2024 17:52:19 +0000 Subject: [PATCH 3/3] Add changelog entry --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index f9b892d..c31655b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -141,6 +141,7 @@ v0.13.0 - Add a mapping compatible with Plex and ffmpeg for the "original date" fields. - Remove an unnecessary dependency on `six`. +- Replace `imghdr` with `filetype` to support Python 3.13. v0.12.0 '''''''