8000 Rewrite audio.py to jive with image.py (#91886) · python/cpython@4403320 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4403320

Browse files
authored
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
1 parent e93d2fb commit 4403320

File tree

6 files changed

+78
-64
lines changed

6 files changed

+78
-64
lines changed

Lib/email/mime/audio.py

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,58 +11,6 @@
1111
from email.mime.nonmultipart import MIMENonMultipart
1212

1313

14-
_tests = []
15-
16-
def _test_aifc_aiff(h, f):
17-
if not h.startswith(b'FORM'):
18-
return None
19-
if h[8:12] in {b'AIFC', b'AIFF'}:
20-
return 'x-aiff'
21-
else:
22-
return None
23-
24-
_tests.append(_test_aifc_aiff)
25-
26-
27-
def _test_au(h, f):
28-
if h.startswith(b'.snd'):
29-
return 'basic'
30-
else:
31-
return None
32-
33-
_tests.append(_test_au)
34-
35-
36-
def _test_wav(h, f):
37-
import wave
38-
# 'RIFF' <len> 'WAVE' 'fmt ' <len>
39-
if not h.startswith(b'RIFF') or h[8:12] != b'WAVE' or h[12:16] != b'fmt ':
40-
return None
41-
else:
42-
return "x-wav"
43-
44-
_tests.append(_test_wav)
45-
46-
47-
# There are others in sndhdr that don't have MIME types. :(
48-
# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma??
49-
def _whatsnd(data):
50-
"""Try to identify a sound file type.
51-
52-
sndhdr.what() has a pretty cruddy interface, unfortunately. This is why
53-
we re-do it here. It would be easier to reverse engineer the Unix 'file'
54-
command and use the standard 'magic' file, as shipped with a modern Unix.
55-
"""
56-
hdr = data[:512]
57-
fakefile = BytesIO(hdr)
58-
for testfn in _tests:
59-
res = testfn(hdr, fakefile)
60-
if res is not None:
61-
return res
62-
else:
63-
return None
64-
65-
6614
class MIMEAudio(MIMENonMultipart):
6715
"""Class for generating audio/* MIME documents."""
6816

@@ -89,10 +37,64 @@ def __init__(self, _audiodata, _subtype=None,
8937
header.
9038
"""
9139
if _subtype is None:
92-
_subtype = _whatsnd(_audiodata)
40+
_subtype = _what(_audiodata)
9341
if _subtype is None:
9442
raise TypeError('Could not find audio MIME subtype')
9543
MIMENonMultipart.__init__(self, 'audio', _subtype, policy=policy,
9644
**_params)
9745
self.set_payload(_audiodata)
9846
_encoder(self)
47+
48+
49+
_rules = []
50+
51+
52+
# Originally from the sndhdr module.
53+
#
54+
# There are others in sndhdr that don't have MIME types. :(
55+
# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma??
56+
def _what(data):
57+
# Try to identify a sound file type.
58+
#
59+
# sndhdr.what() had a pretty cruddy interface, unfortunately. This is why
60+
# we re-do it here. It would be easier to reverse engineer the Unix 'file'
61+
# command and use the standard 'magic' file, as shipped with a modern Unix.
62+
hdr = data[:512]
63+
fakefile = BytesIO(hdr)
64+
for testfn in _rules:
65+
if res := testfn(hdr, fakefile):
66+
return res
67+
else:
68+
return None
69+
70+
71+
def rule(rulefunc):
72+
_rules.append(rulefunc)
73+
return rulefunc
74+
75+
76+
@rule
77+
def _aiff(h, f):
78+
if not h.startswith(b'FORM'):
79+
return None
80+
if h[8:12] in {b'AIFC', b'AIFF'}:
81+
return 'x-aiff'
82+
else:
83+
return None
84+
85+
86+
@rule
87+
def _au(h, f):
88+
if h.startswith(b'.snd'):
89+
return 'basic'
90+
else:
91+
return None
92+
93+
94+
@rule
95+
def _wav(h, f):
96+
# 'RIFF' <len> 'WAVE' 'fmt ' <len>
97+
if not h.startswith(b'RIFF') or h[8:12] != b'WAVE' or h[12:16] != b'fmt ':
98+
return None
99+
else:
100+
return "x-wav"

Lib/test/test_email/data/sndhdr.aifc

106 Bytes
Binary file not shown.

Lib/test/test_email/data/sndhdr.aiff

108 Bytes
Binary file not shown.

Lib/test/test_email/data/sndhdr.wav

64 Bytes
Binary file not shown.

Lib/test/test_email/test_email.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,37 +1515,49 @@ def test_multipart_with_bad_bytes_in_cte(self):
15151515

15161516
# Test the basic MIMEAudio class
15171517
class TestMIMEAudio(unittest.TestCase):
1518-
def setUp(self):
1519-
with openfile('audiotest.au', 'rb') as fp:
1518+
def _make_audio(self, ext):
1519+
with openfile(f'sndhdr.{ext}', 'rb') as fp:
15201520
self._audiodata = fp.read()
15211521
self._au = MIMEAudio(self._audiodata)
15221522

15231523
def test_guess_minor_type(self):
1524-
self.assertEqual(self._au.get_content_type(), 'audio/basic')
1524+
for ext, subtype in {
1525+
'aifc': 'x-aiff',
1526+
'aiff': 'x-aiff',
1527+
'wav': 'x-wav',
1528+
'au': 'basic',
1529+
}.items():
1530+
self._make_audio(ext)
1531+
subtype = ext if subtype is None else subtype
1532+
self.assertEqual(self._au.get_content_type(), f'audio/{subtype}')
15251533

15261534
def test_encoding(self):
1535+
self._make_audio('au')
15271536
payload = self._au.get_payload()
15281537
self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')),
1529-
self._audiodata)
1538+
self._audiodata)
15301539

15311540
def test_checkSetMinor(self):
1541+
self._make_audio('au')
15321542
au = MIMEAudio(self._audiodata, 'fish')
15331543
self.assertEqual(au.get_content_type(), 'audio/fish')
15341544

15351545
def test_add_header(self):
1546+
self._make_audio('au')
15361547
eq = self.assertEqual
15371548
self._au.add_header('Content-Disposition', 'attachment',
1538-
filename='audiotest.au')
1549+
filename='sndhdr.au')
15391550
eq(self._au['content-disposition'],
1540-
'attachment; filename="audiotest.au"')
1551+
'attachment; filename="sndhdr.au"')
15411552
eq(self._au.get_params(header='content-disposition'),
1542-
[('attachment', ''), ('filename', 'audiotest.au')])
1553+
[('attachment', ''), ('filename', 'sndhdr.au')])
15431554
eq(self._au.get_param('filename', header='content-disposition'),
1544-
'audiotest.au')
1555+
'sndhdr.au')
15451556
missing = []
15461557
eq(self._au.get_param('attachment', header='content-disposition'), '')
1547-
self.assertIs(self._au.get_param('foo', failobj=missing,
1548-
header='content-disposition'), missing)
1558+
self.assertIs(self._au.get_param(
1559+
'foo', failobj=missing,
1560+
header='content-disposition'), missing)
15491561
# Try some missing stuff
15501562
self.assertIs(self._au.get_param('foobar', missing), missing)
15511563
self.assertIs(self._au.get_param('attachment', missing,
@@ -3462,7 +3474,7 @@ def test_BytesGenerator_linend_with_non_ascii(self):
34623474
self.assertEqual(s.getvalue(), msgtxt)
34633475

34643476
def test_mime_classes_policy_argument(self):
3465-
with openfile('audiotest.au', 'rb') as fp:
3477+
with openfile('sndhdr.au', 'rb') as fp:
34663478
audiodata = fp.read()
34673479
with openfile('python.gif', 'rb') as fp:
34683480
bindata = fp.read()

0 commit comments

Comments
 (0)
0