Skip to content

Commit 22eff88

Browse files
[3.15] gh-93417: Improve test_mimetypes (GH-150725) (GH-153748)
* Separate tests for module-level API and for the MimeTypes class. * Add tests for mimetypes.init() and MimeTypes() with knownfiles and with explicitly passed files. (cherry picked from commit b23646a)
1 parent 29e733a commit 22eff88

2 files changed

Lines changed: 203 additions & 153 deletions

File tree

Lib/test/mime.types2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# MIME type Extensions
2+
testing/test2 test test2
3+
testing/test3 test test3

Lib/test/test_mimetypes.py

Lines changed: 200 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -31,50 +31,11 @@ def tearDownModule():
3131
mimetypes.knownfiles = knownfiles
3232

3333

34-
class MimeTypesTestCase(unittest.TestCase):
34+
class MimeTypesModuleTestCase(unittest.TestCase):
3535
def setUp(self):
36-
self.db = mimetypes.MimeTypes()
37-
38-
def test_case_sensitivity(self):
39-
eq = self.assertEqual
40-
eq(self.db.guess_file_type("foobar.html"), ("text/html", None))
41-
eq(self.db.guess_type("scheme:foobar.html"), ("text/html", None))
42-
eq(self.db.guess_file_type("foobar.HTML"), ("text/html", None))
43-
eq(self.db.guess_type("scheme:foobar.HTML"), ("text/html", None))
44-
eq(self.db.guess_file_type("foobar.tgz"), ("application/x-tar", "gzip"))
45-
eq(self.db.guess_type("scheme:foobar.tgz"), ("application/x-tar", "gzip"))
46-
eq(self.db.guess_file_type("foobar.TGZ"), ("application/x-tar", "gzip"))
47-
eq(self.db.guess_type("scheme:foobar.TGZ"), ("application/x-tar", "gzip"))
48-
eq(self.db.guess_file_type("foobar.tar.Z"), ("application/x-tar", "compress"))
49-
eq(self.db.guess_type("scheme:foobar.tar.Z"), ("application/x-tar", "compress"))
50-
eq(self.db.guess_file_type("foobar.tar.z"), (None, None))
51-
eq(self.db.guess_type("scheme:foobar.tar.z"), (None, None))
52-
53-
def test_default_data(self):
54-
eq = self.assertEqual
55-
eq(self.db.guess_file_type("foo.html"), ("text/html", None))
56-
eq(self.db.guess_file_type("foo.HTML"), ("text/html", None))
57-
eq(self.db.guess_file_type("foo.tgz"), ("application/x-tar", "gzip"))
58-
eq(self.db.guess_file_type("foo.tar.gz"), ("application/x-tar", "gzip"))
59-
eq(self.db.guess_file_type("foo.tar.Z"), ("application/x-tar", "compress"))
60-
eq(self.db.guess_file_type("foo.tar.bz2"), ("application/x-tar", "bzip2"))
61-
eq(self.db.guess_file_type("foo.tar.xz"), ("application/x-tar", "xz"))
62-
63-
def test_data_urls(self):
64-
eq = self.assertEqual
65-
guess_type = self.db.guess_type
66-
eq(guess_type("data:invalidDataWithoutComma"), (None, None))
67-
eq(guess_type("data:,thisIsTextPlain"), ("text/plain", None))
68-
eq(guess_type("data:;base64,thisIsTextPlain"), ("text/plain", None))
69-
eq(guess_type("data:text/x-foo,thisIsTextXFoo"), ("text/x-foo", None))
70-
71-
def test_file_parsing(self):
72-
eq = self.assertEqual
73-
sio = io.StringIO("x-application/x-unittest pyunit\n")
74-
self.db.readfp(sio)
75-
eq(self.db.guess_file_type("foo.pyunit"),
76-
("x-application/x-unittest", None))
77-
eq(self.db.guess_extension("x-application/x-unittest"), ".pyunit")
36+
mimetypes.inited = False
37+
mimetypes._default_mime_types()
38+
mimetypes._db = None
7839

7940
def test_read_mime_types(self):
8041
eq = self.assertEqual
@@ -109,100 +70,6 @@ def test_read_mime_types(self):
10970
mock_open.assert_called_with(filename, encoding='utf-8')
11071
eq(mime_dict[".Français"], "application/no-mans-land")
11172

112-
def test_non_standard_types(self):
113-
eq = self.assertEqual
114-
# First try strict
115-
eq(self.db.guess_file_type('foo.xul', strict=True), (None, None))
116-
# And then non-strict
117-
eq(self.db.guess_file_type('foo.xul', strict=False), ('text/xul', None))
118-
eq(self.db.guess_file_type('foo.XUL', strict=False), ('text/xul', None))
119-
eq(self.db.guess_file_type('foo.invalid', strict=False), (None, None))
120-
eq(self.db.guess_extension('image/jpeg', strict=False), '.jpg')
121-
eq(self.db.guess_extension('image/JPEG', strict=False), '.jpg')
122-
123-
def test_filename_with_url_delimiters(self):
124-
# bpo-38449: URL delimiters cases should be handled also.
125-
# They would have different mime types if interpreted as URL as
126-
# compared to when interpreted as filename because of the semicolon.
127-
eq = self.assertEqual
128-
gzip_expected = ('application/x-tar', 'gzip')
129-
for name in (
130-
';1.tar.gz',
131-
'?1.tar.gz',
132-
'#1.tar.gz',
133-
'#1#.tar.gz',
134-
';1#.tar.gz',
135-
';&1=123;?.tar.gz',
136-
'?k1=v1&k2=v2.tar.gz',
137-
):
138-
for prefix in ('', '/', '\\',
139-
'c:', 'c:/', 'c:\\', 'c:/d/', 'c:\\d\\',
140-
'//share/server/', '\\\\share\\server\\'):
141-
path = prefix + name
142-
with self.subTest(path=path):
143-
eq(self.db.guess_file_type(path), gzip_expected)
144-
eq(self.db.guess_type(path), gzip_expected)
145-
expected = (None, None) if os.name == 'nt' else gzip_expected
146-
for prefix in ('//', '\\\\', '//share/', '\\\\share\\'):
147-
path = prefix + name
148-
with self.subTest(path=path):
149-
eq(self.db.guess_file_type(path), expected)
150-
eq(self.db.guess_type(path), expected)
151-
eq(self.db.guess_file_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected)
152-
eq(self.db.guess_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected)
153-
154-
eq(self.db.guess_file_type(r'foo/.tar.gz'), (None, 'gzip'))
155-
eq(self.db.guess_type(r'foo/.tar.gz'), (None, 'gzip'))
156-
expected = (None, 'gzip') if os.name == 'nt' else gzip_expected
157-
eq(self.db.guess_file_type(r'foo\.tar.gz'), expected)
158-
eq(self.db.guess_type(r'foo\.tar.gz'), expected)
159-
eq(self.db.guess_type(r'scheme:foo\.tar.gz'), gzip_expected)
160-
161-
def test_url(self):
162-
result = self.db.guess_type('http://example.com/host.html')
163-
result = self.db.guess_type('http://host.html')
164-
msg = 'URL only has a host name, not a file'
165-
self.assertSequenceEqual(result, (None, None), msg)
166-
result = self.db.guess_type('http://example.com/host.html')
167-
msg = 'Should be text/html'
168-
self.assertSequenceEqual(result, ('text/html', None), msg)
169-
result = self.db.guess_type('http://example.com/host.html#x.tar')
170-
self.assertSequenceEqual(result, ('text/html', None))
171-
result = self.db.guess_type('http://example.com/host.html?q=x.tar')
172-
self.assertSequenceEqual(result, ('text/html', None))
173-
174-
def test_guess_all_types(self):
175-
# First try strict. Use a set here for testing the results because if
176-
# test_urllib2 is run before test_mimetypes, global state is modified
177-
# such that the 'all' set will have more items in it.
178-
all = self.db.guess_all_extensions('text/plain', strict=True)
179-
self.assertTrue(set(all) >= {'.bat', '.c', '.h', '.ksh', '.pl', '.txt'})
180-
self.assertEqual(len(set(all)), len(all)) # no duplicates
181-
# And now non-strict
182-
all = self.db.guess_all_extensions('image/jpeg', strict=False)
183-
self.assertEqual(all, ['.jpg', '.jpe', '.jpeg'])
184-
# And now for no hits
185-
all = self.db.guess_all_extensions('image/jpg', strict=True)
186-
self.assertEqual(all, [])
187-
# And now for type existing in both strict and non-strict mappings.
188-
self.db.add_type('test-type', '.strict-ext')
189-
self.db.add_type('test-type', '.non-strict-ext', strict=False)
190-
all = self.db.guess_all_extensions('test-type', strict=False)
191-
self.assertEqual(all, ['.strict-ext', '.non-strict-ext'])
192-
all = self.db.guess_all_extensions('test-type')
193-
self.assertEqual(all, ['.strict-ext'])
194-
# Test that changing the result list does not affect the global state
195-
all.append('.no-such-ext')
196-
all = self.db.guess_all_extensions('test-type')
197-
self.assertNotIn('.no-such-ext', all)
198-
199-
def test_encoding(self):
200-
filename = support.findfile("mime.types")
201-
mimes = mimetypes.MimeTypes([filename])
202-
exts = mimes.guess_all_extensions('application/vnd.geocube+xml',
203-
strict=True)
204-
self.assertEqual(exts, ['.g3', '.g\xb3'])
205-
20673
def test_init_reinitializes(self):
20774
# Issue 4936: make sure an init starts clean
20875
# First, put some poison into the types table
@@ -341,6 +208,202 @@ def test_init_stability(self):
341208
self.assertEqual(types_map, mimetypes.types_map)
342209
self.assertEqual(common_types, mimetypes.common_types)
343210

211+
def test_init_files(self):
212+
guess_file_type = mimetypes.guess_file_type
213+
self.assertEqual(guess_file_type("file.test2")[0], None)
214+
215+
filename = support.findfile("mime.types2")
216+
mimetypes.init([filename])
217+
self.assertEqual(guess_file_type("file.test2")[0], "testing/test2")
218+
219+
mimetypes.init()
220+
self.assertEqual(guess_file_type("file.test2")[0], None)
221+
222+
def test_init_knownfiles(self):
223+
guess_file_type = mimetypes.guess_file_type
224+
self.assertEqual(guess_file_type("file.test2")[0], None)
225+
226+
filename = support.findfile("mime.types2")
227+
mimetypes.knownfiles = [filename, "non-existent"]
228+
self.addCleanup(mimetypes.knownfiles.clear)
229+
230+
mimetypes.init()
231+
self.assertEqual(guess_file_type("file.test2")[0], "testing/test2")
232+
233+
def test_added_types_are_used(self):
234+
mimetypes.add_type('testing/default-type', '')
235+
mime_type, _ = mimetypes.guess_type('')
236+
self.assertEqual(mime_type, 'testing/default-type')
237+
238+
mime_type, _ = mimetypes.guess_type('test.myext')
239+
self.assertEqual(mime_type, None)
240+
241+
mimetypes.add_type('testing/type', '.myext')
242+
mime_type, _ = mimetypes.guess_type('test.myext')
243+
self.assertEqual(mime_type, 'testing/type')
244+
245+
def test_add_type_with_undotted_extension_deprecated(self):
246+
with self.assertWarns(DeprecationWarning):
247+
mimetypes.add_type("testing/type", "undotted")
248+
249+
250+
class MimeTypesClassTestCase(unittest.TestCase):
251+
def setUp(self):
252+
self.db = mimetypes.MimeTypes()
253+
254+
def test_init_files(self):
255+
guess_file_type = self.db.guess_file_type
256+
self.assertEqual(guess_file_type("file.test2")[0], None)
257+
258+
filename = support.findfile("mime.types2")
259+
db = mimetypes.MimeTypes([filename])
260+
guess_file_type = db.guess_file_type
261+
self.assertEqual(guess_file_type("file.test2")[0], "testing/test2")
262+
263+
def test_init_knownfiles(self):
264+
filename = support.findfile("mime.types2")
265+
mimetypes.knownfiles = [filename, "non-existent"]
266+
self.addCleanup(mimetypes.knownfiles.clear)
267+
268+
db = mimetypes.MimeTypes()
269+
guess_file_type = db.guess_file_type
270+
self.assertEqual(guess_file_type("file.test2")[0], None)
271+
272+
def test_case_sensitivity(self):
273+
eq = self.assertEqual
274+
eq(self.db.guess_file_type("foobar.html"), ("text/html", None))
275+
eq(self.db.guess_type("scheme:foobar.html"), ("text/html", None))
276+
eq(self.db.guess_file_type("foobar.HTML"), ("text/html", None))
277+
eq(self.db.guess_type("scheme:foobar.HTML"), ("text/html", None))
278+
eq(self.db.guess_file_type("foobar.tgz"), ("application/x-tar", "gzip"))
279+
eq(self.db.guess_type("scheme:foobar.tgz"), ("application/x-tar", "gzip"))
280+
eq(self.db.guess_file_type("foobar.TGZ"), ("application/x-tar", "gzip"))
281+
eq(self.db.guess_type("scheme:foobar.TGZ"), ("application/x-tar", "gzip"))
282+
eq(self.db.guess_file_type("foobar.tar.Z"), ("application/x-tar", "compress"))
283+
eq(self.db.guess_type("scheme:foobar.tar.Z"), ("application/x-tar", "compress"))
284+
eq(self.db.guess_file_type("foobar.tar.z"), (None, None))
285+
eq(self.db.guess_type("scheme:foobar.tar.z"), (None, None))
286+
287+
def test_default_data(self):
288+
eq = self.assertEqual
289+
eq(self.db.guess_file_type("foo.html"), ("text/html", None))
290+
eq(self.db.guess_file_type("foo.HTML"), ("text/html", None))
291+
eq(self.db.guess_file_type("foo.tgz"), ("application/x-tar", "gzip"))
292+
eq(self.db.guess_file_type("foo.tar.gz"), ("application/x-tar", "gzip"))
293+
eq(self.db.guess_file_type("foo.tar.Z"), ("application/x-tar", "compress"))
294+
eq(self.db.guess_file_type("foo.tar.bz2"), ("application/x-tar", "bzip2"))
295+
eq(self.db.guess_file_type("foo.tar.xz"), ("application/x-tar", "xz"))
296+
297+
def test_data_urls(self):
298+
eq = self.assertEqual
299+
guess_type = self.db.guess_type
300+
eq(guess_type("data:invalidDataWithoutComma"), (None, None))
301+
eq(guess_type("data:,thisIsTextPlain"), ("text/plain", None))
302+
eq(guess_type("data:;base64,thisIsTextPlain"), ("text/plain", None))
303+
eq(guess_type("data:text/x-foo,thisIsTextXFoo"), ("text/x-foo", None))
304+
305+
def test_file_parsing(self):
306+
eq = self.assertEqual
307+
sio = io.StringIO("x-application/x-unittest pyunit\n")
308+
self.db.readfp(sio)
309+
eq(self.db.guess_file_type("foo.pyunit"),
310+
("x-application/x-unittest", None))
311+
eq(self.db.guess_extension("x-application/x-unittest"), ".pyunit")
312+
313+
def test_non_standard_types(self):
314+
eq = self.assertEqual
315+
# First try strict
316+
eq(self.db.guess_file_type('foo.xul', strict=True), (None, None))
317+
# And then non-strict
318+
eq(self.db.guess_file_type('foo.xul', strict=False), ('text/xul', None))
319+
eq(self.db.guess_file_type('foo.XUL', strict=False), ('text/xul', None))
320+
eq(self.db.guess_file_type('foo.invalid', strict=False), (None, None))
321+
eq(self.db.guess_extension('image/jpeg', strict=False), '.jpg')
322+
eq(self.db.guess_extension('image/JPEG', strict=False), '.jpg')
323+
324+
def test_filename_with_url_delimiters(self):
325+
# bpo-38449: URL delimiters cases should be handled also.
326+
# They would have different mime types if interpreted as URL as
327+
# compared to when interpreted as filename because of the semicolon.
328+
eq = self.assertEqual
329+
gzip_expected = ('application/x-tar', 'gzip')
330+
for name in (
331+
';1.tar.gz',
332+
'?1.tar.gz',
333+
'#1.tar.gz',
334+
'#1#.tar.gz',
335+
';1#.tar.gz',
336+
';&1=123;?.tar.gz',
337+
'?k1=v1&k2=v2.tar.gz',
338+
):
339+
for prefix in ('', '/', '\\',
340+
'c:', 'c:/', 'c:\\', 'c:/d/', 'c:\\d\\',
341+
'//share/server/', '\\\\share\\server\\'):
342+
path = prefix + name
343+
with self.subTest(path=path):
344+
eq(self.db.guess_file_type(path), gzip_expected)
345+
eq(self.db.guess_type(path), gzip_expected)
346+
expected = (None, None) if os.name == 'nt' else gzip_expected
347+
for prefix in ('//', '\\\\', '//share/', '\\\\share\\'):
348+
path = prefix + name
349+
with self.subTest(path=path):
350+
eq(self.db.guess_file_type(path), expected)
351+
eq(self.db.guess_type(path), expected)
352+
eq(self.db.guess_file_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected)
353+
eq(self.db.guess_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected)
354+
355+
eq(self.db.guess_file_type(r'foo/.tar.gz'), (None, 'gzip'))
356+
eq(self.db.guess_type(r'foo/.tar.gz'), (None, 'gzip'))
357+
expected = (None, 'gzip') if os.name == 'nt' else gzip_expected
358+
eq(self.db.guess_file_type(r'foo\.tar.gz'), expected)
359+
eq(self.db.guess_type(r'foo\.tar.gz'), expected)
360+
eq(self.db.guess_type(r'scheme:foo\.tar.gz'), gzip_expected)
361+
362+
def test_url(self):
363+
result = self.db.guess_type('http://example.com/host.html')
364+
result = self.db.guess_type('http://host.html')
365+
msg = 'URL only has a host name, not a file'
366+
self.assertSequenceEqual(result, (None, None), msg)
367+
result = self.db.guess_type('http://example.com/host.html')
368+
msg = 'Should be text/html'
369+
self.assertSequenceEqual(result, ('text/html', None), msg)
370+
result = self.db.guess_type('http://example.com/host.html#x.tar')
371+
self.assertSequenceEqual(result, ('text/html', None))
372+
result = self.db.guess_type('http://example.com/host.html?q=x.tar')
373+
self.assertSequenceEqual(result, ('text/html', None))
374+
375+
def test_guess_all_types(self):
376+
# First try strict. Use a set here for testing the results because if
377+
# test_urllib2 is run before test_mimetypes, global state is modified
378+
# such that the 'all' set will have more items in it.
379+
all = self.db.guess_all_extensions('text/plain', strict=True)
380+
self.assertTrue(set(all) >= {'.bat', '.c', '.h', '.ksh', '.pl', '.txt'})
381+
self.assertEqual(len(set(all)), len(all)) # no duplicates
382+
# And now non-strict
383+
all = self.db.guess_all_extensions('image/jpeg', strict=False)
384+
self.assertEqual(all, ['.jpg', '.jpe', '.jpeg'])
385+
# And now for no hits
386+
all = self.db.guess_all_extensions('image/jpg', strict=True)
387+
self.assertEqual(all, [])
388+
# And now for type existing in both strict and non-strict mappings.
389+
self.db.add_type('test-type', '.strict-ext')
390+
self.db.add_type('test-type', '.non-strict-ext', strict=False)
391+
all = self.db.guess_all_extensions('test-type', strict=False)
392+
self.assertEqual(all, ['.strict-ext', '.non-strict-ext'])
393+
all = self.db.guess_all_extensions('test-type')
394+
self.assertEqual(all, ['.strict-ext'])
395+
# Test that changing the result list does not affect the global state
396+
all.append('.no-such-ext')
397+
all = self.db.guess_all_extensions('test-type')
398+
self.assertNotIn('.no-such-ext', all)
399+
400+
def test_encoding(self):
401+
filename = support.findfile("mime.types")
402+
mimes = mimetypes.MimeTypes([filename])
403+
exts = mimes.guess_all_extensions('application/vnd.geocube+xml',
404+
strict=True)
405+
self.assertEqual(exts, ['.g3', '.g\xb3'])
406+
344407
def test_path_like_ob(self):
345408
filename = "LICENSE.txt"
346409
filepath = os_helper.FakePath(filename)
@@ -378,22 +441,6 @@ def test_keywords_args_api(self):
378441
self.assertEqual(self.db.guess_all_extensions(
379442
type='image/jpeg', strict=True), ['.jpg', '.jpe', '.jpeg'])
380443

381-
def test_added_types_are_used(self):
382-
mimetypes.add_type('testing/default-type', '')
383-
mime_type, _ = mimetypes.guess_type('')
384-
self.assertEqual(mime_type, 'testing/default-type')
385-
386-
mime_type, _ = mimetypes.guess_type('test.myext')
387-
self.assertEqual(mime_type, None)
388-
389-
mimetypes.add_type('testing/type', '.myext')
390-
mime_type, _ = mimetypes.guess_type('test.myext')
391-
self.assertEqual(mime_type, 'testing/type')
392-
393-
def test_add_type_with_undotted_extension_deprecated(self):
394-
with self.assertWarns(DeprecationWarning):
395-
mimetypes.add_type("testing/type", "undotted")
396-
397444

398445
@unittest.skipUnless(sys.platform.startswith("win"), "Windows only")
399446
class Win32MimeTypesTestCase(unittest.TestCase):

0 commit comments

Comments
 (0)