Skip to content

Commit

Permalink
Merge pull request #75 from geigerzaehler/replace-imghdr
Browse files Browse the repository at this point in the history
Replace deprecated `imghdr` package with `filetype`
  • Loading branch information
jackwilsdon authored Nov 3, 2024
2 parents 6accdc4 + 182f3dd commit e1de364
Show file tree
Hide file tree
Showing 5 changed files with 7 additions and 53 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
'''''''
Expand Down
47 changes: 5 additions & 42 deletions mediafile.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
import codecs
import datetime
import enum
import filetype
import functools
import imghdr
import logging
import math
import os
Expand Down Expand Up @@ -78,8 +78,6 @@
'wav': 'WAVE',
}

PREFERRED_IMAGE_EXTENSIONS = {'jpeg': 'jpg'}


# Exceptions.

Expand Down Expand Up @@ -346,52 +344,17 @@ 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)
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):
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
Binary file removed test/rsrc/only-magic-bytes.jpg
Binary file not shown.
11 changes: 0 additions & 11 deletions test/test_mediafile_edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,6 @@ def test_old_ape_version_bitrate(self):
f = mediafile.MediaFile(media_file)
self.assertEqual(f.bitrate, 0)

def test_only_magic_bytes_jpeg(self):
# Some jpeg files can only be recognized by their magic bytes and as
# such aren't recognized by imghdr. Ensure that this still works thanks
# to our own follow up mimetype detection based on
# https://github.com/file/file/blob/master/magic/Magdir/jpeg#L12
magic_bytes_file = os.path.join(_common.RSRC, b'only-magic-bytes.jpg')
with open(magic_bytes_file, 'rb') as f:
jpg_data = f.read()
self.assertEqual(
mediafile._imghdr_what_wrapper(jpg_data), 'jpeg')

def test_soundcheck_non_ascii(self):
# Make sure we don't crash when the iTunes SoundCheck field contains
# non-ASCII binary data.
Expand Down

0 comments on commit e1de364

Please sign in to comment.