Skip to content

gh-102542 Refactor the mime audio module #102540

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
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')