Skip to content
62 changes: 8 additions & 54 deletions Lib/email/mime/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

__all__ = ['MIMEAudio']

from io import BytesIO
from email import encoders
from email.mime.nonmultipart import MIMENonMultipart

Expand Down Expand Up @@ -36,65 +35,20 @@ def __init__(self, _audiodata, _subtype=None,
constructor, which turns them into parameters on the Content-Type
header.
"""
if _subtype is None:
_subtype = _what(_audiodata)
if _subtype is None:
raise TypeError('Could not find audio MIME subtype')
_subtype = _subtype or _infer_subtype(_audiodata)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the behavior if _subtype is '' (or any other non-None null value). Someone other than me needs to agree with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. Falsey values other than None such as: 0, False, '' and empty collections will all fall back to the second or operand: _infer_subtype(_audiodata).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer more explicit tests than just "falseiness" when a more explicit type is indicated. In this case _subtype=None defaults to None to mean that this argument wasn't given.

MIMENonMultipart.__init__(self, 'audio', _subtype, policy=policy,
**_params)
self.set_payload(_audiodata)
_encoder(self)


_rules = []


# Originally from the sndhdr module.
#
# There are others in sndhdr that don't have MIME types. :(
# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma??
def _what(data):
# Try to identify a sound file type.
#
# sndhdr.what() had a pretty cruddy interface, unfortunately. This is why
# we re-do it here. It would be easier to reverse engineer the Unix 'file'
# command and use the standard 'magic' file, as shipped with a modern Unix.
hdr = data[:512]
fakefile = BytesIO(hdr)
for testfn in _rules:
if res := testfn(hdr, fakefile):
return res
else:
return None


def rule(rulefunc):
_rules.append(rulefunc)
return rulefunc


@rule
def _aiff(h, f):
if not h.startswith(b'FORM'):
return None
if h[8:12] in {b'AIFC', b'AIFF'}:
def _infer_subtype(h: bytes) -> str:
"""Infer the audio format based on the data's header"""
if h.startswith(b'FORM') and h[8:12] in (b'AIFC', b'AIFF'):
return 'x-aiff'
else:
return None


@rule
def _au(h, f):
if h.startswith(b'.snd'):
elif h.startswith(b'.snd'):
return 'basic'
else:
return None

elif h.startswith(b'RIFF') and h[8:16] == b'WAVEfmt ':
return 'x-wav'

@rule
def _wav(h, f):
# 'RIFF' <len> 'WAVE' 'fmt ' <len>
if not h.startswith(b'RIFF') or h[8:12] != b'WAVE' or h[12:16] != b'fmt ':
return None
else:
return "x-wav"
raise TypeError('Could not find audio MIME subtype')