Tachyon /Users/simon/.local/share/uv/python/cpython-3.15.0-macos-aarch64-none/lib/python3.15/mimetypes.py
2
Self Samples
19
Cumulative
4
Lines Hit
0.07%
% of Total
2
Max Self
6
Max Total
Intensity:
Cold Hot
Self Time
Total Time
Show All
Hot Only
Heat
Specialization
Line
Self
Total
Code
1
"""Guess the MIME type of a file.
2
3
This module defines two useful functions:
4
5
guess_type(url, strict=True) -- guess the MIME type and encoding of a URL.
6
7
guess_extension(type, strict=True) -- guess the extension for a given MIME type.
8
9
It also contains the following, for tuning the behavior:
10
11
Data:
12
13
knownfiles -- list of files to parse
14
inited -- flag set when init() has been called
15
suffix_map -- dictionary mapping suffixes to suffixes
16
encodings_map -- dictionary mapping suffixes to encodings
17
types_map -- dictionary mapping suffixes to types
18
19
Functions:
20
21
init([files]) -- parse a list of files, default knownfiles (on Windows, the
22
default values are taken from the registry)
23
read_mime_types(file) -- parse one file, return a dictionary or None
24
"""
25
26
try:
27
from _winapi import _mimetypes_read_windows_registry
28
except ImportError:
29
_mimetypes_read_windows_registry = None
30
31
try:
32
import winreg as _winreg
33
except ImportError:
34
_winreg = None
35
36
__all__ = [
37
"knownfiles", "inited", "MimeTypes",
38
"guess_type", "guess_file_type", "guess_all_extensions", "guess_extension",
39
"add_type", "init", "read_mime_types",
40
"suffix_map", "encodings_map", "types_map", "common_types"
41
]
42
43
knownfiles = [
44
"/etc/mime.types",
45
"/etc/httpd/mime.types", # Mac OS X
46
"/etc/httpd/conf/mime.types", # Apache
47
"/etc/apache/mime.types", # Apache 1
48
"/etc/apache2/mime.types", # Apache 2
49
"/usr/local/etc/httpd/conf/mime.types",
50
"/usr/local/lib/netscape/mime.types",
51
"/usr/local/etc/httpd/conf/mime.types", # Apache 1.2
52
"/usr/local/etc/mime.types", # Apache 1.3
53
]
54
55
inited = False
56
_db = None
57
58
59
class MimeTypes:
60
"""MIME-types datastore.
61
62
This datastore can handle information from mime.types-style files
63
and supports basic determination of MIME type from a filename or
64
URL, and can guess a reasonable extension given a MIME type.
65
"""
66
67
def __init__(self, filenames=(), strict=True):
68
if not inited:
69
init()
70
self.encodings_map = _encodings_map_default.copy()
71
self.suffix_map = _suffix_map_default.copy()
72
self.types_map = ({}, {}) # dict for (non-strict, strict)
73
self.types_map_inv = ({}, {})
74
for (ext, type) in _types_map_default.items():
75
self.add_type(type, ext, True)
76
for (ext, type) in _common_types_default.items():
77
self.add_type(type, ext, False)
78
for name in filenames:
79
self.read(name, strict)
80
81
def add_type(self, type, ext, strict=True):
82
"""Add a mapping between a type and an extension.
83
84
When the extension is already known, the new
85
type will replace the old one. When the type
86
is already known the extension will be added
87
to the list of known extensions.
88
89
If strict is true, information will be added to
90
list of standard types, else to the list of non-standard
91
types.
92
93
Valid extensions are empty or start with a '.'.
94
"""
95
if ext and not ext.startswith('.'):
96
from warnings import _deprecated
97
98
_deprecated(
99
"Undotted extensions",
100
"Using undotted extensions is deprecated and "
101
"will raise a ValueError in Python {remove}",
102
remove=(3, 16),
103
)
104
105
if not type:
106
return
107
self.types_map[strict][ext] = type
108
exts = self.types_map_inv[strict].setdefault(type, [])
109
if ext not in exts:
110
exts.append(ext)
111
112
def guess_type(self, url, strict=True):
113
"""Guess the type of a file which is either a URL or a path-like object.
114
115
Return value is a tuple (type, encoding) where type is None if
116
the type can't be guessed (no or unknown suffix) or a string
117
of the form type/subtype, usable for a MIME Content-type
118
header; and encoding is None for no encoding or the name of
119
the program used to encode (e.g. compress or gzip). The
120
mappings are table driven. Encoding suffixes are case
121
sensitive; type suffixes are first tried case sensitive, then
122
case insensitive.
123
124
The suffixes .tgz, .taz and .tz (case sensitive!) are all
125
mapped to '.tar.gz'. (This is table-driven too, using the
126
dictionary suffix_map.)
127
128
Optional 'strict' argument when False adds a bunch of commonly found,
129
but non-standard types.
130
"""
131
# Lazy import to improve module import time
132
import os
133
import urllib.parse
134
135
# TODO: Deprecate accepting file paths (in particular path-like objects).
136
url = os.fspath(url)
137
p = urllib.parse.urlparse(url)
138
if p.scheme and len(p.scheme) > 1:
139
scheme = p.scheme
140
url = p.path
141
else:
142
2
6
return self.guess_file_type(url, strict=strict)
143
if scheme == 'data':
144
# syntax of data URLs:
145
# dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
146
# mediatype := [ type "/" subtype ] *( ";" parameter )
147
# data := *urlchar
148
# parameter := attribute "=" value
149
# type/subtype defaults to "text/plain"
150
comma = url.find(',')
151
if comma < 0:
152
# bad data URL
153
return None, None
154
semi = url.find(';', 0, comma)
155
if semi >= 0:
156
type = url[:semi]
157
else:
158
type = url[:comma]
159
if '=' in type or '/' not in type:
160
type = 'text/plain'
161
return type, None # never compressed, so encoding is None
162
163
# Lazy import to improve module import time
164
import posixpath
165
166
return self._guess_file_type(url, strict, posixpath.splitext)
167
168
def guess_file_type(self, path, *, strict=True):
169
"""Guess the type of a file based on its path.
170
171
Similar to guess_type(), but takes file path instead of URL.
172
"""
173
# Lazy import to improve module import time
174
import os
175
176
path = os.fsdecode(path)
177
path = os.path.splitdrive(path)[1]
178
4
return self._guess_file_type(path, strict, os.path.splitext)
179
180
def _guess_file_type(self, path, strict, splitext):
181
3
base, ext = splitext(path)
182
while (ext_lower := ext.lower()) in self.suffix_map:
183
base, ext = splitext(base + self.suffix_map[ext_lower])
184
# encodings_map is case sensitive
185
if ext in self.encodings_map:
186
encoding = self.encodings_map[ext]
187
base, ext = splitext(base)
188
else:
189
encoding = None
190
ext = ext.lower()
191
types_map = self.types_map[True]
192
if ext in types_map:
193
return types_map[ext], encoding
194
elif strict:
195
return None, encoding
196
types_map = self.types_map[False]
197
if ext in types_map:
198
return types_map[ext], encoding
199
else:
200
return None, encoding
201
202
def guess_all_extensions(self, type, strict=True):
203
"""Guess the extensions for a file based on its MIME type.
204
205
Return value is a list of strings giving the possible filename
206
extensions, including the leading dot ('.'). The extension is not
207
guaranteed to have been associated with any particular data stream,
208
but would be mapped to the MIME type 'type' by guess_type().
209
210
Optional 'strict' argument when false adds a bunch of commonly found,
211
but non-standard types.
212
"""
213
type = type.lower()
214
extensions = list(self.types_map_inv[True].get(type, []))
215
if not strict:
216
for ext in self.types_map_inv[False].get(type, []):
217
if ext not in extensions:
218
extensions.append(ext)
219
return extensions
220
221
def guess_extension(self, type, strict=True):
222
"""Guess the extension for a file based on its MIME type.
223
224
Return value is a string giving a filename extension,
225
including the leading dot ('.'). The extension is not
226
guaranteed to have been associated with any particular data
227
stream, but would be mapped to the MIME type 'type' by
228
guess_type(). If no extension can be guessed for 'type', None
229
is returned.
230
231
Optional 'strict' argument when false adds a bunch of commonly found,
232
but non-standard types.
233
"""
234
extensions = self.guess_all_extensions(type, strict)
235
if not extensions:
236
return None
237
return extensions[0]
238
239
def read(self, filename, strict=True):
240
"""
241
Read a single mime.types-format file, specified by pathname.
242
243
If strict is true, information will be added to
244
list of standard types, else to the list of non-standard
245
types.
246
"""
247
with open(filename, encoding='utf-8') as fp:
248
self.readfp(fp, strict)
249
250
def readfp(self, fp, strict=True):
251
"""
252
Read a single mime.types-format file.
253
254
If strict is true, information will be added to
255
list of standard types, else to the list of non-standard
256
types.
257
"""
258
while line := fp.readline():
259
words = line.split()
260
for i in range(len(words)):
261
if words[i][0] == '#':
262
del words[i:]
263
break
264
if not words:
265
continue
266
type, suffixes = words[0], words[1:]
267
for suff in suffixes:
268
self.add_type(type, '.' + suff, strict)
269
270
def read_windows_registry(self, strict=True):
271
"""
272
Load the MIME types database from Windows registry.
273
274
If strict is true, information will be added to
275
list of standard types, else to the list of non-standard
276
types.
277
"""
278
279
if not _mimetypes_read_windows_registry and not _winreg:
280
return
281
282
add_type = self.add_type
283
if strict:
284
add_type = lambda type, ext: self.add_type(type, ext, True)
285
286
# Accelerated function if it is available
287
if _mimetypes_read_windows_registry:
288
_mimetypes_read_windows_registry(add_type)
289
elif _winreg:
290
self._read_windows_registry(add_type)
291
292
@classmethod
293
def _read_windows_registry(cls, add_type):
294
def enum_types(mimedb):
295
i = 0
296
while True:
297
try:
298
ctype = _winreg.EnumKey(mimedb, i)
299
except OSError:
300
break
301
else:
302
if '\0' not in ctype:
303
yield ctype
304
i += 1
305
306
with _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, '') as hkcr:
307
for subkeyname in enum_types(hkcr):
308
try:
309
with _winreg.OpenKey(hkcr, subkeyname) as subkey:
310
# Only check file extensions
311
if not subkeyname.startswith("."):
312
continue
313
# raises OSError if no 'Content Type' value
314
mimetype, datatype = _winreg.QueryValueEx(
315
subkey, 'Content Type')
316
if datatype != _winreg.REG_SZ:
317
continue
318
add_type(mimetype, subkeyname)
319
except OSError:
320
continue
321
322
def guess_type(url, strict=True):
323
"""Guess the type of a file based on its URL.
324
325
Return value is a tuple (type, encoding) where type is None if the
326
type can't be guessed (no or unknown suffix) or a string of the
327
form type/subtype, usable for a MIME Content-type header; and
328
encoding is None for no encoding or the name of the program used
329
to encode (e.g. compress or gzip). The mappings are table
330
driven. Encoding suffixes are case sensitive; type suffixes are
331
first tried case sensitive, then case insensitive.
332
333
The suffixes .tgz, .taz and .tz (case sensitive!) are all mapped
334
to ".tar.gz". (This is table-driven too, using the dictionary
335
suffix_map).
336
337
Optional 'strict' argument when false adds a bunch of commonly found, but
338
non-standard types.
339
"""
340
if _db is None:
341
init()
342
6
return _db.guess_type(url, strict)
343
344
345
def guess_file_type(path, *, strict=True):
346
"""Guess the type of a file based on its path.
347
348
Similar to guess_type(), but takes file path instead of URL.
349
"""
350
if _db is None:
351
init()
352
return _db.guess_file_type(path, strict=strict)
353
354
355
def guess_all_extensions(type, strict=True):
356
"""Guess the extensions for a file based on its MIME type.
357
358
Return value is a list of strings giving the possible filename
359
extensions, including the leading dot ('.'). The extension is not
360
guaranteed to have been associated with any particular data
361
stream, but would be mapped to the MIME type 'type' by
362
guess_type(). If no extension can be guessed for 'type', None
363
is returned.
364
365
Optional 'strict' argument when false adds a bunch of commonly found,
366
but non-standard types.
367
"""
368
if _db is None:
369
init()
370
return _db.guess_all_extensions(type, strict)
371
372
def guess_extension(type, strict=True):
373
"""Guess the extension for a file based on its MIME type.
374
375
Return value is a string giving a filename extension, including the
376
leading dot ('.'). The extension is not guaranteed to have been
377
associated with any particular data stream, but would be mapped to the
378
MIME type 'type' by guess_type(). If no extension can be guessed for
379
'type', None is returned.
380
381
Optional 'strict' argument when false adds a bunch of commonly found,
382
but non-standard types.
383
"""
384
if _db is None:
385
init()
386
return _db.guess_extension(type, strict)
387
388
def add_type(type, ext, strict=True):
389
"""Add a mapping between a type and an extension.
390
391
When the extension is already known, the new
392
type will replace the old one. When the type
393
is already known the extension will be added
394
to the list of known extensions.
395
396
If strict is true, information will be added to
397
list of standard types, else to the list of non-standard
398
types.
399
"""
400
if _db is None:
401
init()
402
return _db.add_type(type, ext, strict)
403
404
405
def init(files=None):
406
global suffix_map, types_map, encodings_map, common_types
407
global inited, _db
408
inited = True # so that MimeTypes.__init__() doesn't call us again
409
410
if files is None or _db is None:
411
db = MimeTypes()
412
# Quick return if not supported
413
db.read_windows_registry()
414
415
if files is None:
416
files = knownfiles
417
else:
418
files = knownfiles + list(files)
419
else:
420
db = _db
421
422
# Lazy import to improve module import time
423
import os
424
425
for file in files:
426
if os.path.isfile(file):
427
db.read(file)
428
encodings_map = db.encodings_map
429
suffix_map = db.suffix_map
430
types_map = db.types_map[True]
431
common_types = db.types_map[False]
432
# Make the DB a global variable now that it is fully initialized
433
_db = db
434
435
436
def read_mime_types(file):
437
try:
438
f = open(file, encoding='utf-8')
439
except OSError:
440
return None
441
with f:
442
db = MimeTypes()
443
db.readfp(f, True)
444
return db.types_map[True]
445
446
447
def _default_mime_types():
448
global suffix_map, _suffix_map_default
449
global encodings_map, _encodings_map_default
450
global types_map, _types_map_default
451
global common_types, _common_types_default
452
453
suffix_map = _suffix_map_default = {
454
'.svgz': '.svg.gz',
455
'.tgz': '.tar.gz',
456
'.taz': '.tar.gz',
457
'.tz': '.tar.gz',
458
'.tbz2': '.tar.bz2',
459
'.txz': '.tar.xz',
460
}
461
462
encodings_map = _encodings_map_default = {
463
'.gz': 'gzip',
464
'.Z': 'compress',
465
'.bz2': 'bzip2',
466
'.xz': 'xz',
467
'.br': 'br',
468
}
469
470
# Before adding new types, make sure they are either registered with IANA,
471
# at https://www.iana.org/assignments/media-types/media-types.xhtml
472
# or extensions, i.e. using the x- prefix
473
474
# If you add to these, please keep them sorted by mime type.
475
# Make sure the entry with the preferred file extension for a particular mime type
476
# appears before any others of the same mimetype.
477
types_map = _types_map_default = {
478
'.js' : 'text/javascript',
479
'.mjs' : 'text/javascript',
480
'.dcm' : 'application/dicom',
481
'.efi' : 'application/efi',
482
'.epub' : 'application/epub+zip',
483
'.gz' : 'application/gzip',
484
'.json' : 'application/json',
485
'.webmanifest': 'application/manifest+json',
486
'.doc' : 'application/msword',
487
'.dot' : 'application/msword',
488
'.wiz' : 'application/msword',
489
'.nq' : 'application/n-quads',
490
'.nt' : 'application/n-triples',
491
'.cjs' : 'application/node',
492
'.bin' : 'application/octet-stream',
493
'.a' : 'application/octet-stream',
494
'.o' : 'application/octet-stream',
495
'.obj' : 'application/octet-stream',
496
'.so' : 'application/octet-stream',
497
'.oda' : 'application/oda',
498
'.ogx' : 'application/ogg',
499
'.pdf' : 'application/pdf',
500
'.ai' : 'application/pdf',
501
'.p7c' : 'application/pkcs7-mime',
502
'.ps' : 'application/postscript',
503
'.eps' : 'application/postscript',
504
'.rtf' : 'application/rtf',
505
'.sql' : 'application/sql',
506
'.texi' : 'application/texinfo',
507
'.texinfo': 'application/texinfo',
508
'.toml' : 'application/toml',
509
'.trig' : 'application/trig',
510
'.m3u' : 'application/vnd.apple.mpegurl',
511
'.m3u8' : 'application/vnd.apple.mpegurl',
512
'.dll' : 'application/vnd.microsoft.portable-executable',
513
'.exe' : 'application/vnd.microsoft.portable-executable',
514
'.cab' : 'application/vnd.ms-cab-compressed',
515
'.xls' : 'application/vnd.ms-excel',
516
'.xlb' : 'application/vnd.ms-excel',
517
'.eot' : 'application/vnd.ms-fontobject',
518
'.chm' : 'application/vnd.ms-htmlhelp',
519
'.thmx' : 'application/vnd.ms-officetheme',
520
'.ppt' : 'application/vnd.ms-powerpoint',
521
'.pot' : 'application/vnd.ms-powerpoint',
522
'.ppa' : 'application/vnd.ms-powerpoint',
523
'.pps' : 'application/vnd.ms-powerpoint',
524
'.pwz' : 'application/vnd.ms-powerpoint',
525
'.odg' : 'application/vnd.oasis.opendocument.graphics',
526
'.odp' : 'application/vnd.oasis.opendocument.presentation',
527
'.ods' : 'application/vnd.oasis.opendocument.spreadsheet',
528
'.odt' : 'application/vnd.oasis.opendocument.text',
529
'.pptx' : 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
530
'.xlsx' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
531
'.docx' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
532
'.rar' : 'application/vnd.rar',
533
'.sqlite3': 'application/vnd.sqlite3',
534
'.sqlite' : 'application/vnd.sqlite3',
535
'.wasm' : 'application/wasm',
536
'.7z' : 'application/x-7z-compressed',
537
'.bcpio' : 'application/x-bcpio',
538
'.cpio' : 'application/x-cpio',
539
'.csh' : 'application/x-csh',
540
'.deb' : 'application/x-debian-package',
541
'.dvi' : 'application/x-dvi',
542
'.gtar' : 'application/x-gtar',
543
'.hdf' : 'application/x-hdf',
544
'.h5' : 'application/x-hdf5',
545
'.latex' : 'application/x-latex',
546
'.mif' : 'application/x-mif',
547
'.cdf' : 'application/x-netcdf',
548
'.nc' : 'application/x-netcdf',
549
'.p12' : 'application/x-pkcs12',
550
'.php' : 'application/x-httpd-php',
551
'.pfx' : 'application/x-pkcs12',
552
'.ram' : 'application/x-pn-realaudio',
553
'.pyc' : 'application/x-python-code',
554
'.pyo' : 'application/x-python-code',
555
'.rpm' : 'application/x-rpm',
556
'.sh' : 'application/x-sh',
557
'.shar' : 'application/x-shar',
558
'.swf' : 'application/x-shockwave-flash',
559
'.sv4cpio': 'application/x-sv4cpio',
560
'.sv4crc' : 'application/x-sv4crc',
561
'.tar' : 'application/x-tar',
562
'.tcl' : 'application/x-tcl',
563
'.tex' : 'application/x-tex',
564
'.roff' : 'application/x-troff',
565
'.t' : 'application/x-troff',
566
'.tr' : 'application/x-troff',
567
'.man' : 'application/x-troff-man',
568
'.me' : 'application/x-troff-me',
569
'.ms' : 'application/x-troff-ms',
570
'.ustar' : 'application/x-ustar',
571
'.src' : 'application/x-wais-source',
572
'.xsl' : 'application/xml',
573
'.rdf' : 'application/xml',
574
'.wsdl' : 'application/xml',
575
'.xpdl' : 'application/xml',
576
'.yaml' : 'application/yaml',
577
'.yml' : 'application/yaml',
578
'.zip' : 'application/zip',
579
'.3gp' : 'audio/3gpp',
580
'.3gpp' : 'audio/3gpp',
581
'.3g2' : 'audio/3gpp2',
582
'.3gpp2' : 'audio/3gpp2',
583
'.aac' : 'audio/aac',
584
'.adts' : 'audio/aac',
585
'.loas' : 'audio/aac',
586
'.ass' : 'audio/aac',
587
'.au' : 'audio/basic',
588
'.snd' : 'audio/basic',
589
'.flac' : 'audio/flac',
590
'.mka' : 'audio/matroska',
591
'.m4a' : 'audio/mp4',
592
'.mp3' : 'audio/mpeg',
593
'.mp2' : 'audio/mpeg',
594
'.ogg' : 'audio/ogg',
595
'.opus' : 'audio/opus',
596
'.aif' : 'audio/x-aiff',
597
'.aifc' : 'audio/x-aiff',
598
'.aiff' : 'audio/x-aiff',
599
'.ra' : 'audio/x-pn-realaudio',
600
'.wav' : 'audio/vnd.wave',
601
'.weba' : 'audio/webm',
602
'.ttc' : 'font/collection',
603
'.otf' : 'font/otf',
604
'.ttf' : 'font/ttf',
605
'.woff' : 'font/woff',
606
'.woff2' : 'font/woff2',
607
'.hjif' : 'haptics/hjif',
608
'.hmpg' : 'haptics/hmpg',
609
'.ivs' : 'haptics/ivs',
610
'.avif' : 'image/avif',
611
'.bmp' : 'image/bmp',
612
'.emf' : 'image/emf',
613
'.fits' : 'image/fits',
614
'.g3' : 'image/g3fax',
615
'.gif' : 'image/gif',
616
'.ief' : 'image/ief',
617
'.jp2' : 'image/jp2',
618
'.jpg' : 'image/jpeg',
619
'.jpe' : 'image/jpeg',
620
'.jpeg' : 'image/jpeg',
621
'.jpm' : 'image/jpm',
622
'.jpx' : 'image/jpx',
623
'.jxl' : 'image/jxl',
624
'.heic' : 'image/heic',
625
'.heif' : 'image/heif',
626
'.png' : 'image/png',
627
'.svg' : 'image/svg+xml',
628
'.t38' : 'image/t38',
629
'.tiff' : 'image/tiff',
630
'.tif' : 'image/tiff',
631
'.tfx' : 'image/tiff-fx',
632
'.ico' : 'image/vnd.microsoft.icon',
633
'.webp' : 'image/webp',
634
'.wmf' : 'image/wmf',
635
'.ras' : 'image/x-cmu-raster',
636
'.pnm' : 'image/x-portable-anymap',
637
'.pbm' : 'image/x-portable-bitmap',
638
'.pgm' : 'image/x-portable-graymap',
639
'.ppm' : 'image/x-portable-pixmap',
640
'.rgb' : 'image/x-rgb',
641
'.xbm' : 'image/x-xbitmap',
642
'.xpm' : 'image/x-xpixmap',
643
'.xwd' : 'image/x-xwindowdump',
644
'.eml' : 'message/rfc822',
645
'.mht' : 'message/rfc822',
646
'.mhtml' : 'message/rfc822',
647
'.nws' : 'message/rfc822',
648
'.gltf' : 'model/gltf+json',
649
'.glb' : 'model/gltf-binary',
650
'.stl' : 'model/stl',
651
'.css' : 'text/css',
652
'.csv' : 'text/csv',
653
'.html' : 'text/html',
654
'.htm' : 'text/html',
655
'.md' : 'text/markdown',
656
'.markdown': 'text/markdown',
657
'.n3' : 'text/n3',
658
'.txt' : 'text/plain',
659
'.bat' : 'text/plain',
660
'.c' : 'text/plain',
661
'.h' : 'text/plain',
662
'.ksh' : 'text/plain',
663
'.pl' : 'text/plain',
664
'.srt' : 'text/plain',
665
'.rtx' : 'text/richtext',
666
'.tsv' : 'text/tab-separated-values',
667
'.vtt' : 'text/vtt',
668
'.py' : 'text/x-python',
669
'.rst' : 'text/x-rst',
670
'.etx' : 'text/x-setext',
671
'.sgm' : 'text/x-sgml',
672
'.sgml' : 'text/x-sgml',
673
'.vcf' : 'text/x-vcard',
674
'.xml' : 'text/xml',
675
'.mkv' : 'video/matroska',
676
'.mk3d' : 'video/matroska-3d',
677
'.mp4' : 'video/mp4',
678
'.mpeg' : 'video/mpeg',
679
'.m1v' : 'video/mpeg',
680
'.mpa' : 'video/mpeg',
681
'.mpe' : 'video/mpeg',
682
'.mpg' : 'video/mpeg',
683
'.ogv' : 'video/ogg',
684
'.mov' : 'video/quicktime',
685
'.qt' : 'video/quicktime',
686
'.webm' : 'video/webm',
687
'.avi' : 'video/vnd.avi',
688
'.m4v' : 'video/x-m4v',
689
'.wmv' : 'video/x-ms-wmv',
690
'.movie' : 'video/x-sgi-movie',
691
}
692
693
# These are non-standard types, commonly found in the wild. They will
694
# only match if strict=0 flag is given to the API methods.
695
696
# Please sort these too
697
common_types = _common_types_default = {
698
'.apk' : 'application/vnd.android.package-archive',
699
'.midi': 'audio/midi',
700
'.mid' : 'audio/midi',
701
'.pict': 'image/pict',
702
'.pct' : 'image/pict',
703
'.pic' : 'image/pict',
704
'.xul' : 'text/xul',
705
}
706
707
708
_default_mime_types()
709
710
711
def _parse_args(args):
712
from argparse import ArgumentParser
713
714
parser = ArgumentParser(
715
description='map filename extensions to MIME types',
716
)
717
parser.add_argument(
718
'-e', '--extension',
719
action='store_true',
720
help='guess extension instead of type'
721
)
722
parser.add_argument(
723
'-l', '--lenient',
724
action='store_true',
725
help='additionally search for common but non-standard types'
726
)
727
parser.add_argument('type', nargs='+', help='a type to search')
728
args = parser.parse_args(args)
729
return args, parser.format_help()
730
731
732
def _main(args=None):
733
"""Run the mimetypes command-line interface and return a text to print."""
734
args, help_text = _parse_args(args)
735
736
results = []
737
if args.extension:
738
for gtype in args.type:
739
guess = guess_extension(gtype, not args.lenient)
740
if guess:
741
results.append(str(guess))
742
else:
743
results.append(f"error: unknown type {gtype}")
744
return results
745
else:
746
for gtype in args.type:
747
guess, encoding = guess_type(gtype, not args.lenient)
748
if guess:
749
results.append(f"type: {guess} encoding: {encoding}")
750
else:
751
results.append(f"error: media type unknown for {gtype}")
752
return results
753
754
755
if __name__ == '__main__':
756
import sys
757
758
results = _main()
759
print("\n".join(results))
760
sys.exit(any(result.startswith("error: ") for result in results))