summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>2022-04-24 22:50:07 (GMT)
committerGitHub <noreply@github.com>2022-04-24 22:50:07 (GMT)
commit440332072706c5e422e6c54a2ec0ebb88e09c85c (patch)
tree76e0e5a12d37b250849b3a23486c33e57dda019c
parente93d2fbddaee329b2e8f405cbb5aec44ca221de6 (diff)
downloadcpython-440332072706c5e422e6c54a2ec0ebb88e09c85c.zip
cpython-440332072706c5e422e6c54a2ec0ebb88e09c85c.tar.gz
cpython-440332072706c5e422e6c54a2ec0ebb88e09c85c.tar.bz2
Rewrite audio.py to jive with image.py (#91886)
Similar to the rewrite of email/mime/image.py and associated test after the deprecation of imghdr.py, thisrewrites email/mime/audio.py and associated tests after the deprecation of sndhdr.py. Closes #91885
-rw-r--r--Lib/email/mime/audio.py108
-rw-r--r--Lib/test/test_email/data/sndhdr.aifcbin0 -> 106 bytes
-rw-r--r--Lib/test/test_email/data/sndhdr.aiffbin0 -> 108 bytes
-rw-r--r--Lib/test/test_email/data/sndhdr.au (renamed from Lib/test/test_email/data/audiotest.au)bin28144 -> 28144 bytes
-rw-r--r--Lib/test/test_email/data/sndhdr.wavbin0 -> 64 bytes
-rw-r--r--Lib/test/test_email/test_email.py34
6 files changed, 78 insertions, 64 deletions
diff --git a/Lib/email/mime/audio.py b/Lib/email/mime/audio.py
index e859c2e..8815f5c 100644
--- a/Lib/email/mime/audio.py
+++ b/Lib/email/mime/audio.py
@@ -11,58 +11,6 @@ from email import encoders
from email.mime.nonmultipart import MIMENonMultipart
-_tests = []
-
-def _test_aifc_aiff(h, f):
- if not h.startswith(b'FORM'):
- return None
- if h[8:12] in {b'AIFC', b'AIFF'}:
- return 'x-aiff'
- else:
- return None
-
-_tests.append(_test_aifc_aiff)
-
-
-def _test_au(h, f):
- if h.startswith(b'.snd'):
- return 'basic'
- else:
- return None
-
-_tests.append(_test_au)
-
-
-def _test_wav(h, f):
- import wave
- # '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"
-
-_tests.append(_test_wav)
-
-
-# There are others in sndhdr that don't have MIME types. :(
-# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma??
-def _whatsnd(data):
- """Try to identify a sound file type.
-
- sndhdr.what() has 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 _tests:
- res = testfn(hdr, fakefile)
- if res is not None:
- return res
- else:
- return None
-
-
class MIMEAudio(MIMENonMultipart):
"""Class for generating audio/* MIME documents."""
@@ -89,10 +37,64 @@ class MIMEAudio(MIMENonMultipart):
header.
"""
if _subtype is None:
- _subtype = _whatsnd(_audiodata)
+ _subtype = _what(_audiodata)
if _subtype is None:
raise TypeError('Could not find audio MIME subtype')
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'}:
+ return 'x-aiff'
+ else:
+ return None
+
+
+@rule
+def _au(h, f):
+ if h.startswith(b'.snd'):
+ return 'basic'
+ else:
+ return None
+
+
+@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"
diff --git a/Lib/test/test_email/data/sndhdr.aifc b/Lib/test/test_email/data/sndhdr.aifc
new file mode 100644
index 0000000..8aae4e7
--- /dev/null
+++ b/Lib/test/test_email/data/sndhdr.aifc
Binary files differ
diff --git a/Lib/test/test_email/data/sndhdr.aiff b/Lib/test/test_email/data/sndhdr.aiff
new file mode 100644
index 0000000..8c279a7
--- /dev/null
+++ b/Lib/test/test_email/data/sndhdr.aiff
Binary files differ
diff --git a/Lib/test/test_email/data/audiotest.au b/Lib/test/test_email/data/sndhdr.au
index f76b050..f76b050 100644
--- a/Lib/test/test_email/data/audiotest.au
+++ b/Lib/test/test_email/data/sndhdr.au
Binary files differ
diff --git a/Lib/test/test_email/data/sndhdr.wav b/Lib/test/test_email/data/sndhdr.wav
new file mode 100644
index 0000000..0dca367
--- /dev/null
+++ b/Lib/test/test_email/data/sndhdr.wav
Binary files differ
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index 6ead594..933aa4c 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -1515,37 +1515,49 @@ Blah blah blah
# Test the basic MIMEAudio class
class TestMIMEAudio(unittest.TestCase):
- def setUp(self):
- with openfile('audiotest.au', 'rb') as fp:
+ def _make_audio(self, ext):
+ with openfile(f'sndhdr.{ext}', 'rb') as fp:
self._audiodata = fp.read()
self._au = MIMEAudio(self._audiodata)
def test_guess_minor_type(self):
- self.assertEqual(self._au.get_content_type(), 'audio/basic')
+ for ext, subtype in {
+ 'aifc': 'x-aiff',
+ 'aiff': 'x-aiff',
+ 'wav': 'x-wav',
+ 'au': 'basic',
+ }.items():
+ self._make_audio(ext)
+ subtype = ext if subtype is None else subtype
+ self.assertEqual(self._au.get_content_type(), f'audio/{subtype}')
def test_encoding(self):
+ self._make_audio('au')
payload = self._au.get_payload()
self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')),
- self._audiodata)
+ self._audiodata)
def test_checkSetMinor(self):
+ self._make_audio('au')
au = MIMEAudio(self._audiodata, 'fish')
self.assertEqual(au.get_content_type(), 'audio/fish')
def test_add_header(self):
+ self._make_audio('au')
eq = self.assertEqual
self._au.add_header('Content-Disposition', 'attachment',
- filename='audiotest.au')
+ filename='sndhdr.au')
eq(self._au['content-disposition'],
- 'attachment; filename="audiotest.au"')
+ 'attachment; filename="sndhdr.au"')
eq(self._au.get_params(header='content-disposition'),
- [('attachment', ''), ('filename', 'audiotest.au')])
+ [('attachment', ''), ('filename', 'sndhdr.au')])
eq(self._au.get_param('filename', header='content-disposition'),
- 'audiotest.au')
+ 'sndhdr.au')
missing = []
eq(self._au.get_param('attachment', header='content-disposition'), '')
- self.assertIs(self._au.get_param('foo', failobj=missing,
- header='content-disposition'), missing)
+ self.assertIs(self._au.get_param(
+ 'foo', failobj=missing,
+ header='content-disposition'), missing)
# Try some missing stuff
self.assertIs(self._au.get_param('foobar', missing), missing)
self.assertIs(self._au.get_param('attachment', missing,
@@ -3462,7 +3474,7 @@ multipart/report
self.assertEqual(s.getvalue(), msgtxt)
def test_mime_classes_policy_argument(self):
- with openfile('audiotest.au', 'rb') as fp:
+ with openfile('sndhdr.au', 'rb') as fp:
audiodata = fp.read()
with openfile('python.gif', 'rb') as fp:
bindata = fp.read()