mirror of
https://github.com/python/cpython.git
synced 2025-11-01 10:45:30 +00:00
gh-91520: Rewrite imghdr inlining for clarity and completeness (#91521)
* Rewrite imghdr inlining for clarity and completeness * Move MIMEImage class back closer to the top of the file since it's the important thing. * Use a decorate to mark a given rule function and simplify the rule function names for clarity. * Copy over all the imghdr test data files into the email package's test data directory. This way when imghdr is actually removed, it won't affect the MIMEImage guessing tests. * Rewrite and extend the MIMEImage tests to test for all supported auto-detected MIME image subtypes. * Remove the now redundant PyBanner048.gif data file. * See https://github.com/python/cpython/pull/91461#discussion_r850313336 Co-authored-by: Oleg Iarygin <dralife@yandex.ru> Co-authored-by: Oleg Iarygin <dralife@yandex.ru>
This commit is contained in:
parent
ee475430d4
commit
1fcb39ea64
17 changed files with 152 additions and 117 deletions
|
|
@ -10,109 +10,6 @@ from email import encoders
|
|||
from email.mime.nonmultipart import MIMENonMultipart
|
||||
|
||||
|
||||
# Originally from the imghdr module.
|
||||
def _what(h):
|
||||
for tf in tests:
|
||||
if res := tf(h):
|
||||
return res
|
||||
else:
|
||||
return None
|
||||
|
||||
tests = []
|
||||
|
||||
def _test_jpeg(h):
|
||||
"""JPEG data with JFIF or Exif markers; and raw JPEG"""
|
||||
if h[6:10] in (b'JFIF', b'Exif'):
|
||||
return 'jpeg'
|
||||
elif h[:4] == b'\xff\xd8\xff\xdb':
|
||||
return 'jpeg'
|
||||
|
||||
tests.append(_test_jpeg)
|
||||
|
||||
def _test_png(h):
|
||||
if h.startswith(b'\211PNG\r\n\032\n'):
|
||||
return 'png'
|
||||
|
||||
tests.append(_test_png)
|
||||
|
||||
def _test_gif(h):
|
||||
"""GIF ('87 and '89 variants)"""
|
||||
if h[:6] in (b'GIF87a', b'GIF89a'):
|
||||
return 'gif'
|
||||
|
||||
tests.append(_test_gif)
|
||||
|
||||
def _test_tiff(h):
|
||||
"""TIFF (can be in Motorola or Intel byte order)"""
|
||||
if h[:2] in (b'MM', b'II'):
|
||||
return 'tiff'
|
||||
|
||||
tests.append(_test_tiff)
|
||||
|
||||
def _test_rgb(h):
|
||||
"""SGI image library"""
|
||||
if h.startswith(b'\001\332'):
|
||||
return 'rgb'
|
||||
|
||||
tests.append(_test_rgb)
|
||||
|
||||
def _test_pbm(h):
|
||||
"""PBM (portable bitmap)"""
|
||||
if len(h) >= 3 and \
|
||||
h[0] == ord(b'P') and h[1] in b'14' and h[2] in b' \t\n\r':
|
||||
return 'pbm'
|
||||
|
||||
tests.append(_test_pbm)
|
||||
|
||||
def _test_pgm(h):
|
||||
"""PGM (portable graymap)"""
|
||||
if len(h) >= 3 and \
|
||||
h[0] == ord(b'P') and h[1] in b'25' and h[2] in b' \t\n\r':
|
||||
return 'pgm'
|
||||
|
||||
tests.append(_test_pgm)
|
||||
|
||||
def _test_ppm(h):
|
||||
"""PPM (portable pixmap)"""
|
||||
if len(h) >= 3 and \
|
||||
h[0] == ord(b'P') and h[1] in b'36' and h[2] in b' \t\n\r':
|
||||
return 'ppm'
|
||||
|
||||
tests.append(_test_ppm)
|
||||
|
||||
def _test_rast(h):
|
||||
"""Sun raster file"""
|
||||
if h.startswith(b'\x59\xA6\x6A\x95'):
|
||||
return 'rast'
|
||||
|
||||
tests.append(_test_rast)
|
||||
|
||||
def _test_xbm(h):
|
||||
"""X bitmap (X10 or X11)"""
|
||||
if h.startswith(b'#define '):
|
||||
return 'xbm'
|
||||
|
||||
tests.append(_test_xbm)
|
||||
|
||||
def _test_bmp(h):
|
||||
if h.startswith(b'BM'):
|
||||
return 'bmp'
|
||||
|
||||
tests.append(_test_bmp)
|
||||
|
||||
def _test_webp(h):
|
||||
if h.startswith(b'RIFF') and h[8:12] == b'WEBP':
|
||||
return 'webp'
|
||||
|
||||
tests.append(_test_webp)
|
||||
|
||||
def _test_exr(h):
|
||||
if h.startswith(b'\x76\x2f\x31\x01'):
|
||||
return 'exr'
|
||||
|
||||
tests.append(_test_exr)
|
||||
|
||||
|
||||
class MIMEImage(MIMENonMultipart):
|
||||
"""Class for generating image/* type MIME documents."""
|
||||
|
||||
|
|
@ -137,10 +34,119 @@ class MIMEImage(MIMENonMultipart):
|
|||
constructor, which turns them into parameters on the Content-Type
|
||||
header.
|
||||
"""
|
||||
_subtype = _what(_imagedata) if _subtype is None else _subtype
|
||||
if _subtype is None:
|
||||
if (_subtype := _what(_imagedata)) is None:
|
||||
raise TypeError('Could not guess image MIME subtype')
|
||||
raise TypeError('Could not guess image MIME subtype')
|
||||
MIMENonMultipart.__init__(self, 'image', _subtype, policy=policy,
|
||||
**_params)
|
||||
self.set_payload(_imagedata)
|
||||
_encoder(self)
|
||||
|
||||
|
||||
_rules = []
|
||||
|
||||
|
||||
# Originally from the imghdr module.
|
||||
def _what(data):
|
||||
for rule in _rules:
|
||||
if res := rule(data):
|
||||
return res
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def rule(rulefunc):
|
||||
_rules.append(rulefunc)
|
||||
return rulefunc
|
||||
|
||||
|
||||
@rule
|
||||
def _jpeg(h):
|
||||
"""JPEG data with JFIF or Exif markers; and raw JPEG"""
|
||||
if h[6:10] in (b'JFIF', b'Exif'):
|
||||
return 'jpeg'
|
||||
elif h[:4] == b'\xff\xd8\xff\xdb':
|
||||
return 'jpeg'
|
||||
|
||||
|
||||
@rule
|
||||
def _png(h):
|
||||
if h.startswith(b'\211PNG\r\n\032\n'):
|
||||
return 'png'
|
||||
|
||||
|
||||
@rule
|
||||
def _gif(h):
|
||||
"""GIF ('87 and '89 variants)"""
|
||||
if h[:6] in (b'GIF87a', b'GIF89a'):
|
||||
return 'gif'
|
||||
|
||||
|
||||
@rule
|
||||
def _tiff(h):
|
||||
"""TIFF (can be in Motorola or Intel byte order)"""
|
||||
if h[:2] in (b'MM', b'II'):
|
||||
return 'tiff'
|
||||
|
||||
|
||||
@rule
|
||||
def _rgb(h):
|
||||
"""SGI image library"""
|
||||
if h.startswith(b'\001\332'):
|
||||
return 'rgb'
|
||||
|
||||
|
||||
@rule
|
||||
def _pbm(h):
|
||||
"""PBM (portable bitmap)"""
|
||||
if len(h) >= 3 and \
|
||||
h[0] == ord(b'P') and h[1] in b'14' and h[2] in b' \t\n\r':
|
||||
return 'pbm'
|
||||
|
||||
|
||||
@rule
|
||||
def _pgm(h):
|
||||
"""PGM (portable graymap)"""
|
||||
if len(h) >= 3 and \
|
||||
h[0] == ord(b'P') and h[1] in b'25' and h[2] in b' \t\n\r':
|
||||
return 'pgm'
|
||||
|
||||
|
||||
@rule
|
||||
def _ppm(h):
|
||||
"""PPM (portable pixmap)"""
|
||||
if len(h) >= 3 and \
|
||||
h[0] == ord(b'P') and h[1] in b'36' and h[2] in b' \t\n\r':
|
||||
return 'ppm'
|
||||
|
||||
|
||||
@rule
|
||||
def _rast(h):
|
||||
"""Sun raster file"""
|
||||
if h.startswith(b'\x59\xA6\x6A\x95'):
|
||||
return 'rast'
|
||||
|
||||
|
||||
@rule
|
||||
def _xbm(h):
|
||||
"""X bitmap (X10 or X11)"""
|
||||
if h.startswith(b'#define '):
|
||||
return 'xbm'
|
||||
|
||||
|
||||
@rule
|
||||
def _bmp(h):
|
||||
if h.startswith(b'BM'):
|
||||
return 'bmp'
|
||||
|
||||
|
||||
@rule
|
||||
def _webp(h):
|
||||
if h.startswith(b'RIFF') and h[8:12] == b'WEBP':
|
||||
return 'webp'
|
||||
|
||||
|
||||
@rule
|
||||
def _exr(h):
|
||||
if h.startswith(b'\x76\x2f\x31\x01'):
|
||||
return 'exr'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue