Skip to content

Commit d4e7a84

Browse files
[3.14] gh-93417: Improve test_mimetypes (GH-150725) (GH-153749)
* 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 fb1fb12 commit d4e7a84

2 files changed

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

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

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

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

0 commit comments

Comments
 (0)