mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Bump mimetypes to 3.14.2 (#6808)
* Bump mimetypes to 3.14.2 * Unmark resolved tests * Mark failed test in Windows
This commit is contained in:
1 parent
2df879c5ee
commit
ce1bbc7938
6 files changed
+539
-204
No files matched your search
Vendored
+217
-84
@@ -23,10 +23,11 @@ init([files]) -- parse a list of files, default knownfiles (on Windows, the
|
||||
read_mime_types(file) -- parse one file, return a dictionary or None
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import posixpath
|
||||
import urllib.parse
|
||||
try:
|
||||
from _winapi import _mimetypes_read_windows_registry
|
||||
except ImportError:
|
||||
_mimetypes_read_windows_registry = None
|
||||
|
||||
try:
|
||||
import winreg as _winreg
|
||||
except ImportError:
|
||||
@@ -34,7 +35,7 @@ except ImportError:
|
||||
|
||||
__all__ = [
|
||||
"knownfiles", "inited", "MimeTypes",
|
||||
"guess_type", "guess_all_extensions", "guess_extension",
|
||||
"guess_type", "guess_file_type", "guess_all_extensions", "guess_extension",
|
||||
"add_type", "init", "read_mime_types",
|
||||
"suffix_map", "encodings_map", "types_map", "common_types"
|
||||
]
|
||||
@@ -88,7 +89,21 @@ class MimeTypes:
|
||||
If strict is true, information will be added to
|
||||
list of standard types, else to the list of non-standard
|
||||
types.
|
||||
|
||||
Valid extensions are empty or start with a '.'.
|
||||
"""
|
||||
if ext and not ext.startswith('.'):
|
||||
from warnings import _deprecated
|
||||
|
||||
_deprecated(
|
||||
"Undotted extensions",
|
||||
"Using undotted extensions is deprecated and "
|
||||
"will raise a ValueError in Python {remove}",
|
||||
remove=(3, 16),
|
||||
)
|
||||
|
||||
if not type:
|
||||
return
|
||||
self.types_map[strict][ext] = type
|
||||
exts = self.types_map_inv[strict].setdefault(type, [])
|
||||
if ext not in exts:
|
||||
@@ -110,11 +125,21 @@ class MimeTypes:
|
||||
mapped to '.tar.gz'. (This is table-driven too, using the
|
||||
dictionary suffix_map.)
|
||||
|
||||
Optional `strict' argument when False adds a bunch of commonly found,
|
||||
Optional 'strict' argument when False adds a bunch of commonly found,
|
||||
but non-standard types.
|
||||
"""
|
||||
# Lazy import to improve module import time
|
||||
import os
|
||||
import urllib.parse
|
||||
|
||||
# TODO: Deprecate accepting file paths (in particular path-like objects).
|
||||
url = os.fspath(url)
|
||||
scheme, url = urllib.parse._splittype(url)
|
||||
p = urllib.parse.urlparse(url)
|
||||
if p.scheme and len(p.scheme) > 1:
|
||||
scheme = p.scheme
|
||||
url = p.path
|
||||
else:
|
||||
return self.guess_file_type(url, strict=strict)
|
||||
if scheme == 'data':
|
||||
# syntax of data URLs:
|
||||
# dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
|
||||
@@ -134,26 +159,43 @@ class MimeTypes:
|
||||
if '=' in type or '/' not in type:
|
||||
type = 'text/plain'
|
||||
return type, None # never compressed, so encoding is None
|
||||
base, ext = posixpath.splitext(url)
|
||||
while ext in self.suffix_map:
|
||||
base, ext = posixpath.splitext(base + self.suffix_map[ext])
|
||||
|
||||
# Lazy import to improve module import time
|
||||
import posixpath
|
||||
|
||||
return self._guess_file_type(url, strict, posixpath.splitext)
|
||||
|
||||
def guess_file_type(self, path, *, strict=True):
|
||||
"""Guess the type of a file based on its path.
|
||||
|
||||
Similar to guess_type(), but takes file path instead of URL.
|
||||
"""
|
||||
# Lazy import to improve module import time
|
||||
import os
|
||||
|
||||
path = os.fsdecode(path)
|
||||
path = os.path.splitdrive(path)[1]
|
||||
return self._guess_file_type(path, strict, os.path.splitext)
|
||||
|
||||
def _guess_file_type(self, path, strict, splitext):
|
||||
base, ext = splitext(path)
|
||||
while (ext_lower := ext.lower()) in self.suffix_map:
|
||||
base, ext = splitext(base + self.suffix_map[ext_lower])
|
||||
# encodings_map is case sensitive
|
||||
if ext in self.encodings_map:
|
||||
encoding = self.encodings_map[ext]
|
||||
base, ext = posixpath.splitext(base)
|
||||
base, ext = splitext(base)
|
||||
else:
|
||||
encoding = None
|
||||
ext = ext.lower()
|
||||
types_map = self.types_map[True]
|
||||
if ext in types_map:
|
||||
return types_map[ext], encoding
|
||||
elif ext.lower() in types_map:
|
||||
return types_map[ext.lower()], encoding
|
||||
elif strict:
|
||||
return None, encoding
|
||||
types_map = self.types_map[False]
|
||||
if ext in types_map:
|
||||
return types_map[ext], encoding
|
||||
elif ext.lower() in types_map:
|
||||
return types_map[ext.lower()], encoding
|
||||
else:
|
||||
return None, encoding
|
||||
|
||||
@@ -163,13 +205,13 @@ class MimeTypes:
|
||||
Return value is a list of strings giving the possible filename
|
||||
extensions, including the leading dot ('.'). The extension is not
|
||||
guaranteed to have been associated with any particular data stream,
|
||||
but would be mapped to the MIME type `type' by guess_type().
|
||||
but would be mapped to the MIME type 'type' by guess_type().
|
||||
|
||||
Optional `strict' argument when false adds a bunch of commonly found,
|
||||
Optional 'strict' argument when false adds a bunch of commonly found,
|
||||
but non-standard types.
|
||||
"""
|
||||
type = type.lower()
|
||||
extensions = self.types_map_inv[True].get(type, [])
|
||||
extensions = list(self.types_map_inv[True].get(type, []))
|
||||
if not strict:
|
||||
for ext in self.types_map_inv[False].get(type, []):
|
||||
if ext not in extensions:
|
||||
@@ -182,11 +224,11 @@ class MimeTypes:
|
||||
Return value is a string giving a filename extension,
|
||||
including the leading dot ('.'). The extension is not
|
||||
guaranteed to have been associated with any particular data
|
||||
stream, but would be mapped to the MIME type `type' by
|
||||
guess_type(). If no extension can be guessed for `type', None
|
||||
stream, but would be mapped to the MIME type 'type' by
|
||||
guess_type(). If no extension can be guessed for 'type', None
|
||||
is returned.
|
||||
|
||||
Optional `strict' argument when false adds a bunch of commonly found,
|
||||
Optional 'strict' argument when false adds a bunch of commonly found,
|
||||
but non-standard types.
|
||||
"""
|
||||
extensions = self.guess_all_extensions(type, strict)
|
||||
@@ -213,10 +255,7 @@ class MimeTypes:
|
||||
list of standard types, else to the list of non-standard
|
||||
types.
|
||||
"""
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
while line := fp.readline():
|
||||
words = line.split()
|
||||
for i in range(len(words)):
|
||||
if words[i][0] == '#':
|
||||
@@ -237,10 +276,21 @@ class MimeTypes:
|
||||
types.
|
||||
"""
|
||||
|
||||
# Windows only
|
||||
if not _winreg:
|
||||
if not _mimetypes_read_windows_registry and not _winreg:
|
||||
return
|
||||
|
||||
add_type = self.add_type
|
||||
if strict:
|
||||
add_type = lambda type, ext: self.add_type(type, ext, True)
|
||||
|
||||
# Accelerated function if it is available
|
||||
if _mimetypes_read_windows_registry:
|
||||
_mimetypes_read_windows_registry(add_type)
|
||||
elif _winreg:
|
||||
self._read_windows_registry(add_type)
|
||||
|
||||
@classmethod
|
||||
def _read_windows_registry(cls, add_type):
|
||||
def enum_types(mimedb):
|
||||
i = 0
|
||||
while True:
|
||||
@@ -265,7 +315,7 @@ class MimeTypes:
|
||||
subkey, 'Content Type')
|
||||
if datatype != _winreg.REG_SZ:
|
||||
continue
|
||||
self.add_type(mimetype, subkeyname, strict)
|
||||
add_type(mimetype, subkeyname)
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
@@ -284,7 +334,7 @@ def guess_type(url, strict=True):
|
||||
to ".tar.gz". (This is table-driven too, using the dictionary
|
||||
suffix_map).
|
||||
|
||||
Optional `strict' argument when false adds a bunch of commonly found, but
|
||||
Optional 'strict' argument when false adds a bunch of commonly found, but
|
||||
non-standard types.
|
||||
"""
|
||||
if _db is None:
|
||||
@@ -292,17 +342,27 @@ def guess_type(url, strict=True):
|
||||
return _db.guess_type(url, strict)
|
||||
|
||||
|
||||
def guess_file_type(path, *, strict=True):
|
||||
"""Guess the type of a file based on its path.
|
||||
|
||||
Similar to guess_type(), but takes file path instead of URL.
|
||||
"""
|
||||
if _db is None:
|
||||
init()
|
||||
return _db.guess_file_type(path, strict=strict)
|
||||
|
||||
|
||||
def guess_all_extensions(type, strict=True):
|
||||
"""Guess the extensions for a file based on its MIME type.
|
||||
|
||||
Return value is a list of strings giving the possible filename
|
||||
extensions, including the leading dot ('.'). The extension is not
|
||||
guaranteed to have been associated with any particular data
|
||||
stream, but would be mapped to the MIME type `type' by
|
||||
guess_type(). If no extension can be guessed for `type', None
|
||||
stream, but would be mapped to the MIME type 'type' by
|
||||
guess_type(). If no extension can be guessed for 'type', None
|
||||
is returned.
|
||||
|
||||
Optional `strict' argument when false adds a bunch of commonly found,
|
||||
Optional 'strict' argument when false adds a bunch of commonly found,
|
||||
but non-standard types.
|
||||
"""
|
||||
if _db is None:
|
||||
@@ -315,10 +375,10 @@ def guess_extension(type, strict=True):
|
||||
Return value is a string giving a filename extension, including the
|
||||
leading dot ('.'). The extension is not guaranteed to have been
|
||||
associated with any particular data stream, but would be mapped to the
|
||||
MIME type `type' by guess_type(). If no extension can be guessed for
|
||||
`type', None is returned.
|
||||
MIME type 'type' by guess_type(). If no extension can be guessed for
|
||||
'type', None is returned.
|
||||
|
||||
Optional `strict' argument when false adds a bunch of commonly found,
|
||||
Optional 'strict' argument when false adds a bunch of commonly found,
|
||||
but non-standard types.
|
||||
"""
|
||||
if _db is None:
|
||||
@@ -349,8 +409,8 @@ def init(files=None):
|
||||
|
||||
if files is None or _db is None:
|
||||
db = MimeTypes()
|
||||
if _winreg:
|
||||
db.read_windows_registry()
|
||||
# Quick return if not supported
|
||||
db.read_windows_registry()
|
||||
|
||||
if files is None:
|
||||
files = knownfiles
|
||||
@@ -359,6 +419,9 @@ def init(files=None):
|
||||
else:
|
||||
db = _db
|
||||
|
||||
# Lazy import to improve module import time
|
||||
import os
|
||||
|
||||
for file in files:
|
||||
if os.path.isfile(file):
|
||||
db.read(file)
|
||||
@@ -401,23 +464,28 @@ def _default_mime_types():
|
||||
'.Z': 'compress',
|
||||
'.bz2': 'bzip2',
|
||||
'.xz': 'xz',
|
||||
'.br': 'br',
|
||||
}
|
||||
|
||||
# Before adding new types, make sure they are either registered with IANA,
|
||||
# at http://www.iana.org/assignments/media-types
|
||||
# at https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||
# or extensions, i.e. using the x- prefix
|
||||
|
||||
# If you add to these, please keep them sorted by mime type.
|
||||
# Make sure the entry with the preferred file extension for a particular mime type
|
||||
# appears before any others of the same mimetype.
|
||||
types_map = _types_map_default = {
|
||||
'.js' : 'application/javascript',
|
||||
'.mjs' : 'application/javascript',
|
||||
'.js' : 'text/javascript',
|
||||
'.mjs' : 'text/javascript',
|
||||
'.epub' : 'application/epub+zip',
|
||||
'.gz' : 'application/gzip',
|
||||
'.json' : 'application/json',
|
||||
'.webmanifest': 'application/manifest+json',
|
||||
'.doc' : 'application/msword',
|
||||
'.dot' : 'application/msword',
|
||||
'.wiz' : 'application/msword',
|
||||
'.nq' : 'application/n-quads',
|
||||
'.nt' : 'application/n-triples',
|
||||
'.bin' : 'application/octet-stream',
|
||||
'.a' : 'application/octet-stream',
|
||||
'.dll' : 'application/octet-stream',
|
||||
@@ -426,24 +494,37 @@ def _default_mime_types():
|
||||
'.obj' : 'application/octet-stream',
|
||||
'.so' : 'application/octet-stream',
|
||||
'.oda' : 'application/oda',
|
||||
'.ogx' : 'application/ogg',
|
||||
'.pdf' : 'application/pdf',
|
||||
'.p7c' : 'application/pkcs7-mime',
|
||||
'.ps' : 'application/postscript',
|
||||
'.ai' : 'application/postscript',
|
||||
'.eps' : 'application/postscript',
|
||||
'.trig' : 'application/trig',
|
||||
'.m3u' : 'application/vnd.apple.mpegurl',
|
||||
'.m3u8' : 'application/vnd.apple.mpegurl',
|
||||
'.xls' : 'application/vnd.ms-excel',
|
||||
'.xlb' : 'application/vnd.ms-excel',
|
||||
'.eot' : 'application/vnd.ms-fontobject',
|
||||
'.ppt' : 'application/vnd.ms-powerpoint',
|
||||
'.pot' : 'application/vnd.ms-powerpoint',
|
||||
'.ppa' : 'application/vnd.ms-powerpoint',
|
||||
'.pps' : 'application/vnd.ms-powerpoint',
|
||||
'.pwz' : 'application/vnd.ms-powerpoint',
|
||||
'.odg' : 'application/vnd.oasis.opendocument.graphics',
|
||||
'.odp' : 'application/vnd.oasis.opendocument.presentation',
|
||||
'.ods' : 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'.odt' : 'application/vnd.oasis.opendocument.text',
|
||||
'.pptx' : 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'.xlsx' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'.docx' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'.rar' : 'application/vnd.rar',
|
||||
'.wasm' : 'application/wasm',
|
||||
'.7z' : 'application/x-7z-compressed',
|
||||
'.bcpio' : 'application/x-bcpio',
|
||||
'.cpio' : 'application/x-cpio',
|
||||
'.csh' : 'application/x-csh',
|
||||
'.deb' : 'application/x-debian-package',
|
||||
'.dvi' : 'application/x-dvi',
|
||||
'.gtar' : 'application/x-gtar',
|
||||
'.hdf' : 'application/x-hdf',
|
||||
@@ -453,10 +534,12 @@ def _default_mime_types():
|
||||
'.cdf' : 'application/x-netcdf',
|
||||
'.nc' : 'application/x-netcdf',
|
||||
'.p12' : 'application/x-pkcs12',
|
||||
'.php' : 'application/x-httpd-php',
|
||||
'.pfx' : 'application/x-pkcs12',
|
||||
'.ram' : 'application/x-pn-realaudio',
|
||||
'.pyc' : 'application/x-python-code',
|
||||
'.pyo' : 'application/x-python-code',
|
||||
'.rpm' : 'application/x-rpm',
|
||||
'.sh' : 'application/x-sh',
|
||||
'.shar' : 'application/x-shar',
|
||||
'.swf' : 'application/x-shockwave-flash',
|
||||
@@ -479,29 +562,61 @@ def _default_mime_types():
|
||||
'.rdf' : 'application/xml',
|
||||
'.wsdl' : 'application/xml',
|
||||
'.xpdl' : 'application/xml',
|
||||
'.yaml' : 'application/yaml',
|
||||
'.yml' : 'application/yaml',
|
||||
'.zip' : 'application/zip',
|
||||
'.3gp' : 'audio/3gpp',
|
||||
'.3gpp' : 'audio/3gpp',
|
||||
'.3g2' : 'audio/3gpp2',
|
||||
'.3gpp2' : 'audio/3gpp2',
|
||||
'.aac' : 'audio/aac',
|
||||
'.adts' : 'audio/aac',
|
||||
'.loas' : 'audio/aac',
|
||||
'.ass' : 'audio/aac',
|
||||
'.au' : 'audio/basic',
|
||||
'.snd' : 'audio/basic',
|
||||
'.flac' : 'audio/flac',
|
||||
'.mka' : 'audio/matroska',
|
||||
'.m4a' : 'audio/mp4',
|
||||
'.mp3' : 'audio/mpeg',
|
||||
'.mp2' : 'audio/mpeg',
|
||||
'.ogg' : 'audio/ogg',
|
||||
'.opus' : 'audio/opus',
|
||||
'.aif' : 'audio/x-aiff',
|
||||
'.aifc' : 'audio/x-aiff',
|
||||
'.aiff' : 'audio/x-aiff',
|
||||
'.ra' : 'audio/x-pn-realaudio',
|
||||
'.wav' : 'audio/x-wav',
|
||||
'.wav' : 'audio/vnd.wave',
|
||||
'.otf' : 'font/otf',
|
||||
'.ttf' : 'font/ttf',
|
||||
'.weba' : 'audio/webm',
|
||||
'.woff' : 'font/woff',
|
||||
'.woff2' : 'font/woff2',
|
||||
'.avif' : 'image/avif',
|
||||
'.bmp' : 'image/bmp',
|
||||
'.emf' : 'image/emf',
|
||||
'.fits' : 'image/fits',
|
||||
'.g3' : 'image/g3fax',
|
||||
'.gif' : 'image/gif',
|
||||
'.ief' : 'image/ief',
|
||||
'.jp2' : 'image/jp2',
|
||||
'.jpg' : 'image/jpeg',
|
||||
'.jpe' : 'image/jpeg',
|
||||
'.jpeg' : 'image/jpeg',
|
||||
'.jpm' : 'image/jpm',
|
||||
'.jpx' : 'image/jpx',
|
||||
'.heic' : 'image/heic',
|
||||
'.heif' : 'image/heif',
|
||||
'.png' : 'image/png',
|
||||
'.svg' : 'image/svg+xml',
|
||||
'.t38' : 'image/t38',
|
||||
'.tiff' : 'image/tiff',
|
||||
'.tif' : 'image/tiff',
|
||||
'.tfx' : 'image/tiff-fx',
|
||||
'.ico' : 'image/vnd.microsoft.icon',
|
||||
'.webp' : 'image/webp',
|
||||
'.wmf' : 'image/wmf',
|
||||
'.ras' : 'image/x-cmu-raster',
|
||||
'.bmp' : 'image/x-ms-bmp',
|
||||
'.pnm' : 'image/x-portable-anymap',
|
||||
'.pbm' : 'image/x-portable-bitmap',
|
||||
'.pgm' : 'image/x-portable-graymap',
|
||||
@@ -514,34 +629,49 @@ def _default_mime_types():
|
||||
'.mht' : 'message/rfc822',
|
||||
'.mhtml' : 'message/rfc822',
|
||||
'.nws' : 'message/rfc822',
|
||||
'.gltf' : 'model/gltf+json',
|
||||
'.glb' : 'model/gltf-binary',
|
||||
'.stl' : 'model/stl',
|
||||
'.css' : 'text/css',
|
||||
'.csv' : 'text/csv',
|
||||
'.html' : 'text/html',
|
||||
'.htm' : 'text/html',
|
||||
'.md' : 'text/markdown',
|
||||
'.markdown': 'text/markdown',
|
||||
'.n3' : 'text/n3',
|
||||
'.txt' : 'text/plain',
|
||||
'.bat' : 'text/plain',
|
||||
'.c' : 'text/plain',
|
||||
'.h' : 'text/plain',
|
||||
'.ksh' : 'text/plain',
|
||||
'.pl' : 'text/plain',
|
||||
'.srt' : 'text/plain',
|
||||
'.rtx' : 'text/richtext',
|
||||
'.rtf' : 'text/rtf',
|
||||
'.tsv' : 'text/tab-separated-values',
|
||||
'.vtt' : 'text/vtt',
|
||||
'.py' : 'text/x-python',
|
||||
'.rst' : 'text/x-rst',
|
||||
'.etx' : 'text/x-setext',
|
||||
'.sgm' : 'text/x-sgml',
|
||||
'.sgml' : 'text/x-sgml',
|
||||
'.vcf' : 'text/x-vcard',
|
||||
'.xml' : 'text/xml',
|
||||
'.mkv' : 'video/matroska',
|
||||
'.mk3d' : 'video/matroska-3d',
|
||||
'.mp4' : 'video/mp4',
|
||||
'.mpeg' : 'video/mpeg',
|
||||
'.m1v' : 'video/mpeg',
|
||||
'.mpa' : 'video/mpeg',
|
||||
'.mpe' : 'video/mpeg',
|
||||
'.mpg' : 'video/mpeg',
|
||||
'.ogv' : 'video/ogg',
|
||||
'.mov' : 'video/quicktime',
|
||||
'.qt' : 'video/quicktime',
|
||||
'.webm' : 'video/webm',
|
||||
'.avi' : 'video/x-msvideo',
|
||||
'.avi' : 'video/vnd.avi',
|
||||
'.m4v' : 'video/x-m4v',
|
||||
'.wmv' : 'video/x-ms-wmv',
|
||||
'.movie' : 'video/x-sgi-movie',
|
||||
}
|
||||
|
||||
@@ -551,6 +681,7 @@ def _default_mime_types():
|
||||
# Please sort these too
|
||||
common_types = _common_types_default = {
|
||||
'.rtf' : 'application/rtf',
|
||||
'.apk' : 'application/vnd.android.package-archive',
|
||||
'.midi': 'audio/midi',
|
||||
'.mid' : 'audio/midi',
|
||||
'.jpg' : 'image/jpg',
|
||||
@@ -564,51 +695,53 @@ def _default_mime_types():
|
||||
_default_mime_types()
|
||||
|
||||
|
||||
def _main():
|
||||
import getopt
|
||||
def _parse_args(args):
|
||||
from argparse import ArgumentParser
|
||||
|
||||
USAGE = """\
|
||||
Usage: mimetypes.py [options] type
|
||||
parser = ArgumentParser(
|
||||
description='map filename extensions to MIME types', color=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'-e', '--extension',
|
||||
action='store_true',
|
||||
help='guess extension instead of type'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-l', '--lenient',
|
||||
action='store_true',
|
||||
help='additionally search for common but non-standard types'
|
||||
)
|
||||
parser.add_argument('type', nargs='+', help='a type to search')
|
||||
args = parser.parse_args(args)
|
||||
return args, parser.format_help()
|
||||
|
||||
Options:
|
||||
--help / -h -- print this message and exit
|
||||
--lenient / -l -- additionally search of some common, but non-standard
|
||||
types.
|
||||
--extension / -e -- guess extension instead of type
|
||||
|
||||
More than one type argument may be given.
|
||||
"""
|
||||
def _main(args=None):
|
||||
"""Run the mimetypes command-line interface and return a text to print."""
|
||||
args, help_text = _parse_args(args)
|
||||
|
||||
def usage(code, msg=''):
|
||||
print(USAGE)
|
||||
if msg: print(msg)
|
||||
sys.exit(code)
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'hle',
|
||||
['help', 'lenient', 'extension'])
|
||||
except getopt.error as msg:
|
||||
usage(1, msg)
|
||||
|
||||
strict = 1
|
||||
extension = 0
|
||||
for opt, arg in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
usage(0)
|
||||
elif opt in ('-l', '--lenient'):
|
||||
strict = 0
|
||||
elif opt in ('-e', '--extension'):
|
||||
extension = 1
|
||||
for gtype in args:
|
||||
if extension:
|
||||
guess = guess_extension(gtype, strict)
|
||||
if not guess: print("I don't know anything about type", gtype)
|
||||
else: print(guess)
|
||||
else:
|
||||
guess, encoding = guess_type(gtype, strict)
|
||||
if not guess: print("I don't know anything about type", gtype)
|
||||
else: print('type:', guess, 'encoding:', encoding)
|
||||
results = []
|
||||
if args.extension:
|
||||
for gtype in args.type:
|
||||
guess = guess_extension(gtype, not args.lenient)
|
||||
if guess:
|
||||
results.append(str(guess))
|
||||
else:
|
||||
results.append(f"error: unknown type {gtype}")
|
||||
return results
|
||||
else:
|
||||
for gtype in args.type:
|
||||
guess, encoding = guess_type(gtype, not args.lenient)
|
||||
if guess:
|
||||
results.append(f"type: {guess} encoding: {encoding}")
|
||||
else:
|
||||
results.append(f"error: media type unknown for {gtype}")
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
_main()
|
||||
import sys
|
||||
|
||||
results = _main()
|
||||
print("\n".join(results))
|
||||
sys.exit(any(result.startswith("error: ") for result in results))
|
||||
Vendored
-2
@@ -2098,7 +2098,6 @@ class HTTPSTest(TestCase):
|
||||
h.request('GET', '/')
|
||||
self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED')
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_local_good_hostname(self):
|
||||
# The (valid) cert validates the HTTPS hostname
|
||||
import ssl
|
||||
@@ -2112,7 +2111,6 @@ class HTTPSTest(TestCase):
|
||||
self.addCleanup(resp.close)
|
||||
self.assertEqual(resp.status, 404)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_local_bad_hostname(self):
|
||||
# The (valid) cert doesn't validate the HTTPS hostname
|
||||
import ssl
|
||||
|
||||
Vendored
-11
@@ -498,7 +498,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
|
||||
@unittest.skipUnless(os_helper.TESTFN_NONASCII,
|
||||
'need os_helper.TESTFN_NONASCII')
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_list_dir_nonascii_filename(self):
|
||||
filename = os_helper.TESTFN_NONASCII + '.txt'
|
||||
self.check_list_dir_filename(filename)
|
||||
@@ -519,7 +518,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
'undecodable name cannot be decoded on win32')
|
||||
@unittest.skipUnless(os_helper.TESTFN_UNDECODABLE,
|
||||
'need os_helper.TESTFN_UNDECODABLE')
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_list_dir_undecodable_filename(self):
|
||||
filename = os.fsdecode(os_helper.TESTFN_UNDECODABLE) + '.txt'
|
||||
self.check_list_dir_filename(filename)
|
||||
@@ -536,7 +534,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
|
||||
@unittest.skipUnless(os_helper.TESTFN_UNENCODABLE,
|
||||
'need os_helper.TESTFN_UNENCODABLE')
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_list_dir_unencodable_filename(self):
|
||||
filename = os_helper.TESTFN_UNENCODABLE + '.txt'
|
||||
self.check_list_dir_filename(filename)
|
||||
@@ -550,7 +547,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
self.check_list_dir_dirname(dirname,
|
||||
quotedname=urllib.parse.quote(dirname, safe='&<>\'"'))
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_list_dir_escape_filename(self):
|
||||
# Characters that need special treating in URL or HTML.
|
||||
for name in ('q?', 'f#', '&', '&', '<i>', '"dq"', "'sq'",
|
||||
@@ -618,7 +614,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
# follows that isn't important in this Location: header.
|
||||
self.assertStartsWith(location, 'https://pypi.org/')
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_get(self):
|
||||
#constructs the path relative to the root directory of the HTTPServer
|
||||
response = self.request(self.base_url + '/test')
|
||||
@@ -670,7 +665,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
finally:
|
||||
os.chmod(self.tempdir, 0o755)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_head(self):
|
||||
response = self.request(
|
||||
self.base_url + '/test', method='HEAD')
|
||||
@@ -680,7 +674,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
self.assertEqual(response.getheader('content-type'),
|
||||
'application/octet-stream')
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_browser_cache(self):
|
||||
"""Check that when a request to /test is sent with the request header
|
||||
If-Modified-Since set to date of last modification, the server returns
|
||||
@@ -699,7 +692,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
response = self.request(self.base_url + '/test', headers=headers)
|
||||
self.check_status_and_reason(response, HTTPStatus.NOT_MODIFIED)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_browser_cache_file_changed(self):
|
||||
# with If-Modified-Since earlier than Last-Modified, must return 200
|
||||
dt = self.last_modif_datetime
|
||||
@@ -711,7 +703,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
response = self.request(self.base_url + '/test', headers=headers)
|
||||
self.check_status_and_reason(response, HTTPStatus.OK)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_browser_cache_with_If_None_Match_header(self):
|
||||
# if If-None-Match header is present, ignore If-Modified-Since
|
||||
|
||||
@@ -730,7 +721,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
response = self.request('/', method='GETs')
|
||||
self.check_status_and_reason(response, HTTPStatus.NOT_IMPLEMENTED)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_last_modified(self):
|
||||
"""Checks that the datetime returned in Last-Modified response header
|
||||
is the actual datetime of last modification, rounded to the second
|
||||
@@ -740,7 +730,6 @@ class SimpleHTTPServerTestCase(BaseTestCase):
|
||||
last_modif_header = response.headers['Last-modified']
|
||||
self.assertEqual(last_modif_header, self.last_modif_header)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; http.client.RemoteDisconnected: Remote end closed connection without response
|
||||
def test_path_without_leading_slash(self):
|
||||
response = self.request(self.tempdir_name + '/test')
|
||||
self.check_status_and_reason(response, HTTPStatus.OK, data=self.data)
|
||||
|
||||
Vendored
+321
-105
@@ -1,12 +1,18 @@
|
||||
import io
|
||||
import locale
|
||||
import mimetypes
|
||||
import pathlib
|
||||
import os
|
||||
import shlex
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
import unittest.mock
|
||||
from platform import win32_edition
|
||||
from test import support
|
||||
from test.support import cpython_only, force_not_colorized, os_helper
|
||||
from test.support.import_helper import ensure_lazy_imports
|
||||
|
||||
try:
|
||||
import _winapi
|
||||
except ImportError:
|
||||
_winapi = None
|
||||
|
||||
|
||||
def setUpModule():
|
||||
@@ -28,15 +34,30 @@ class MimeTypesTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.db = mimetypes.MimeTypes()
|
||||
|
||||
def test_case_sensitivity(self):
|
||||
eq = self.assertEqual
|
||||
eq(self.db.guess_file_type("foobar.html"), ("text/html", None))
|
||||
eq(self.db.guess_type("scheme:foobar.html"), ("text/html", None))
|
||||
eq(self.db.guess_file_type("foobar.HTML"), ("text/html", None))
|
||||
eq(self.db.guess_type("scheme:foobar.HTML"), ("text/html", None))
|
||||
eq(self.db.guess_file_type("foobar.tgz"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_type("scheme:foobar.tgz"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_file_type("foobar.TGZ"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_type("scheme:foobar.TGZ"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_file_type("foobar.tar.Z"), ("application/x-tar", "compress"))
|
||||
eq(self.db.guess_type("scheme:foobar.tar.Z"), ("application/x-tar", "compress"))
|
||||
eq(self.db.guess_file_type("foobar.tar.z"), (None, None))
|
||||
eq(self.db.guess_type("scheme:foobar.tar.z"), (None, None))
|
||||
|
||||
def test_default_data(self):
|
||||
eq = self.assertEqual
|
||||
eq(self.db.guess_type("foo.html"), ("text/html", None))
|
||||
eq(self.db.guess_type("foo.HTML"), ("text/html", None))
|
||||
eq(self.db.guess_type("foo.tgz"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_type("foo.tar.gz"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_type("foo.tar.Z"), ("application/x-tar", "compress"))
|
||||
eq(self.db.guess_type("foo.tar.bz2"), ("application/x-tar", "bzip2"))
|
||||
eq(self.db.guess_type("foo.tar.xz"), ("application/x-tar", "xz"))
|
||||
eq(self.db.guess_file_type("foo.html"), ("text/html", None))
|
||||
eq(self.db.guess_file_type("foo.HTML"), ("text/html", None))
|
||||
eq(self.db.guess_file_type("foo.tgz"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_file_type("foo.tar.gz"), ("application/x-tar", "gzip"))
|
||||
eq(self.db.guess_file_type("foo.tar.Z"), ("application/x-tar", "compress"))
|
||||
eq(self.db.guess_file_type("foo.tar.bz2"), ("application/x-tar", "bzip2"))
|
||||
eq(self.db.guess_file_type("foo.tar.xz"), ("application/x-tar", "xz"))
|
||||
|
||||
def test_data_urls(self):
|
||||
eq = self.assertEqual
|
||||
@@ -50,12 +71,10 @@ class MimeTypesTestCase(unittest.TestCase):
|
||||
eq = self.assertEqual
|
||||
sio = io.StringIO("x-application/x-unittest pyunit\n")
|
||||
self.db.readfp(sio)
|
||||
eq(self.db.guess_type("foo.pyunit"),
|
||||
eq(self.db.guess_file_type("foo.pyunit"),
|
||||
("x-application/x-unittest", None))
|
||||
eq(self.db.guess_extension("x-application/x-unittest"), ".pyunit")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_read_mime_types(self):
|
||||
eq = self.assertEqual
|
||||
|
||||
@@ -64,32 +83,40 @@ class MimeTypesTestCase(unittest.TestCase):
|
||||
|
||||
with os_helper.temp_dir() as directory:
|
||||
data = "x-application/x-unittest pyunit\n"
|
||||
file = pathlib.Path(directory, "sample.mimetype")
|
||||
file.write_text(data)
|
||||
file = os.path.join(directory, "sample.mimetype")
|
||||
with open(file, 'w', encoding="utf-8") as f:
|
||||
f.write(data)
|
||||
mime_dict = mimetypes.read_mime_types(file)
|
||||
eq(mime_dict[".pyunit"], "x-application/x-unittest")
|
||||
|
||||
data = "x-application/x-unittest2 pyunit2\n"
|
||||
file = os.path.join(directory, "sample2.mimetype")
|
||||
with open(file, 'w', encoding="utf-8") as f:
|
||||
f.write(data)
|
||||
mime_dict = mimetypes.read_mime_types(os_helper.FakePath(file))
|
||||
eq(mime_dict[".pyunit2"], "x-application/x-unittest2")
|
||||
|
||||
# bpo-41048: read_mime_types should read the rule file with 'utf-8' encoding.
|
||||
# Not with locale encoding. _bootlocale has been imported because io.open(...)
|
||||
# uses it.
|
||||
with os_helper.temp_dir() as directory:
|
||||
data = "application/no-mans-land Fran\u00E7ais"
|
||||
file = pathlib.Path(directory, "sample.mimetype")
|
||||
file.write_text(data, encoding='utf-8')
|
||||
import _bootlocale
|
||||
with support.swap_attr(_bootlocale, 'getpreferredencoding', lambda do_setlocale=True: 'ASCII'):
|
||||
mime_dict = mimetypes.read_mime_types(file)
|
||||
eq(mime_dict[".Français"], "application/no-mans-land")
|
||||
data = "application/no-mans-land Fran\u00E7ais"
|
||||
filename = "filename"
|
||||
fp = io.StringIO(data)
|
||||
with unittest.mock.patch.object(mimetypes, 'open',
|
||||
return_value=fp) as mock_open:
|
||||
mime_dict = mimetypes.read_mime_types(filename)
|
||||
mock_open.assert_called_with(filename, encoding='utf-8')
|
||||
eq(mime_dict[".Français"], "application/no-mans-land")
|
||||
|
||||
def test_non_standard_types(self):
|
||||
eq = self.assertEqual
|
||||
# First try strict
|
||||
eq(self.db.guess_type('foo.xul', strict=True), (None, None))
|
||||
eq(self.db.guess_file_type('foo.xul', strict=True), (None, None))
|
||||
eq(self.db.guess_extension('image/jpg', strict=True), None)
|
||||
# And then non-strict
|
||||
eq(self.db.guess_type('foo.xul', strict=False), ('text/xul', None))
|
||||
eq(self.db.guess_type('foo.XUL', strict=False), ('text/xul', None))
|
||||
eq(self.db.guess_type('foo.invalid', strict=False), (None, None))
|
||||
eq(self.db.guess_file_type('foo.xul', strict=False), ('text/xul', None))
|
||||
eq(self.db.guess_file_type('foo.XUL', strict=False), ('text/xul', None))
|
||||
eq(self.db.guess_file_type('foo.invalid', strict=False), (None, None))
|
||||
eq(self.db.guess_extension('image/jpg', strict=False), '.jpg')
|
||||
eq(self.db.guess_extension('image/JPG', strict=False), '.jpg')
|
||||
|
||||
@@ -99,37 +126,77 @@ class MimeTypesTestCase(unittest.TestCase):
|
||||
# compared to when interpreted as filename because of the semicolon.
|
||||
eq = self.assertEqual
|
||||
gzip_expected = ('application/x-tar', 'gzip')
|
||||
eq(self.db.guess_type(";1.tar.gz"), gzip_expected)
|
||||
eq(self.db.guess_type("?1.tar.gz"), gzip_expected)
|
||||
eq(self.db.guess_type("#1.tar.gz"), gzip_expected)
|
||||
eq(self.db.guess_type("#1#.tar.gz"), gzip_expected)
|
||||
eq(self.db.guess_type(";1#.tar.gz"), gzip_expected)
|
||||
eq(self.db.guess_type(";&1=123;?.tar.gz"), gzip_expected)
|
||||
eq(self.db.guess_type("?k1=v1&k2=v2.tar.gz"), gzip_expected)
|
||||
for name in (
|
||||
';1.tar.gz',
|
||||
'?1.tar.gz',
|
||||
'#1.tar.gz',
|
||||
'#1#.tar.gz',
|
||||
';1#.tar.gz',
|
||||
';&1=123;?.tar.gz',
|
||||
'?k1=v1&k2=v2.tar.gz',
|
||||
):
|
||||
for prefix in ('', '/', '\\',
|
||||
'c:', 'c:/', 'c:\\', 'c:/d/', 'c:\\d\\',
|
||||
'//share/server/', '\\\\share\\server\\'):
|
||||
path = prefix + name
|
||||
with self.subTest(path=path):
|
||||
eq(self.db.guess_file_type(path), gzip_expected)
|
||||
eq(self.db.guess_type(path), gzip_expected)
|
||||
expected = (None, None) if os.name == 'nt' else gzip_expected
|
||||
for prefix in ('//', '\\\\', '//share/', '\\\\share\\'):
|
||||
path = prefix + name
|
||||
with self.subTest(path=path):
|
||||
eq(self.db.guess_file_type(path), expected)
|
||||
eq(self.db.guess_type(path), expected)
|
||||
eq(self.db.guess_file_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected)
|
||||
eq(self.db.guess_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected)
|
||||
|
||||
eq(self.db.guess_file_type(r'foo/.tar.gz'), (None, 'gzip'))
|
||||
eq(self.db.guess_type(r'foo/.tar.gz'), (None, 'gzip'))
|
||||
expected = (None, 'gzip') if os.name == 'nt' else gzip_expected
|
||||
eq(self.db.guess_file_type(r'foo\.tar.gz'), expected)
|
||||
eq(self.db.guess_type(r'foo\.tar.gz'), expected)
|
||||
eq(self.db.guess_type(r'scheme:foo\.tar.gz'), gzip_expected)
|
||||
|
||||
def test_url(self):
|
||||
result = self.db.guess_type('http://example.com/host.html')
|
||||
result = self.db.guess_type('http://host.html')
|
||||
msg = 'URL only has a host name, not a file'
|
||||
self.assertSequenceEqual(result, (None, None), msg)
|
||||
result = self.db.guess_type('http://example.com/host.html')
|
||||
msg = 'Should be text/html'
|
||||
self.assertSequenceEqual(result, ('text/html', None), msg)
|
||||
result = self.db.guess_type('http://example.com/host.html#x.tar')
|
||||
self.assertSequenceEqual(result, ('text/html', None))
|
||||
result = self.db.guess_type('http://example.com/host.html?q=x.tar')
|
||||
self.assertSequenceEqual(result, ('text/html', None))
|
||||
|
||||
def test_guess_all_types(self):
|
||||
eq = self.assertEqual
|
||||
unless = self.assertTrue
|
||||
# First try strict. Use a set here for testing the results because if
|
||||
# test_urllib2 is run before test_mimetypes, global state is modified
|
||||
# such that the 'all' set will have more items in it.
|
||||
all = set(self.db.guess_all_extensions('text/plain', strict=True))
|
||||
unless(all >= set(['.bat', '.c', '.h', '.ksh', '.pl', '.txt']))
|
||||
all = self.db.guess_all_extensions('text/plain', strict=True)
|
||||
self.assertTrue(set(all) >= {'.bat', '.c', '.h', '.ksh', '.pl', '.txt'})
|
||||
self.assertEqual(len(set(all)), len(all)) # no duplicates
|
||||
# And now non-strict
|
||||
all = self.db.guess_all_extensions('image/jpg', strict=False)
|
||||
all.sort()
|
||||
eq(all, ['.jpg'])
|
||||
self.assertEqual(all, ['.jpg'])
|
||||
# And now for no hits
|
||||
all = self.db.guess_all_extensions('image/jpg', strict=True)
|
||||
eq(all, [])
|
||||
self.assertEqual(all, [])
|
||||
# And now for type existing in both strict and non-strict mappings.
|
||||
self.db.add_type('test-type', '.strict-ext')
|
||||
self.db.add_type('test-type', '.non-strict-ext', strict=False)
|
||||
all = self.db.guess_all_extensions('test-type', strict=False)
|
||||
self.assertEqual(all, ['.strict-ext', '.non-strict-ext'])
|
||||
all = self.db.guess_all_extensions('test-type')
|
||||
self.assertEqual(all, ['.strict-ext'])
|
||||
# Test that changing the result list does not affect the global state
|
||||
all.append('.no-such-ext')
|
||||
all = self.db.guess_all_extensions('test-type')
|
||||
self.assertNotIn('.no-such-ext', all)
|
||||
|
||||
def test_encoding(self):
|
||||
getpreferredencoding = locale.getpreferredencoding
|
||||
self.addCleanup(setattr, locale, 'getpreferredencoding',
|
||||
getpreferredencoding)
|
||||
locale.getpreferredencoding = lambda: 'ascii'
|
||||
|
||||
filename = support.findfile("mime.types")
|
||||
mimes = mimetypes.MimeTypes([filename])
|
||||
exts = mimes.guess_all_extensions('application/vnd.geocube+xml',
|
||||
@@ -146,29 +213,110 @@ class MimeTypesTestCase(unittest.TestCase):
|
||||
# Poison should be gone.
|
||||
self.assertEqual(mimetypes.guess_extension('foo/bar'), None)
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith("win"), "Non-Windows only")
|
||||
def test_guess_known_extensions(self):
|
||||
# Issue 37529
|
||||
# The test fails on Windows because Windows adds mime types from the Registry
|
||||
# and that creates some duplicates.
|
||||
from mimetypes import types_map
|
||||
for v in types_map.values():
|
||||
self.assertIsNotNone(mimetypes.guess_extension(v))
|
||||
|
||||
def test_preferred_extension(self):
|
||||
def check_extensions():
|
||||
self.assertEqual(mimetypes.guess_extension('application/octet-stream'), '.bin')
|
||||
self.assertEqual(mimetypes.guess_extension('application/postscript'), '.ps')
|
||||
self.assertEqual(mimetypes.guess_extension('application/vnd.apple.mpegurl'), '.m3u')
|
||||
self.assertEqual(mimetypes.guess_extension('application/vnd.ms-excel'), '.xls')
|
||||
self.assertEqual(mimetypes.guess_extension('application/vnd.ms-powerpoint'), '.ppt')
|
||||
self.assertEqual(mimetypes.guess_extension('application/x-texinfo'), '.texi')
|
||||
self.assertEqual(mimetypes.guess_extension('application/x-troff'), '.roff')
|
||||
self.assertEqual(mimetypes.guess_extension('application/xml'), '.xsl')
|
||||
self.assertEqual(mimetypes.guess_extension('audio/mpeg'), '.mp3')
|
||||
self.assertEqual(mimetypes.guess_extension('image/jpeg'), '.jpg')
|
||||
self.assertEqual(mimetypes.guess_extension('image/tiff'), '.tiff')
|
||||
self.assertEqual(mimetypes.guess_extension('message/rfc822'), '.eml')
|
||||
self.assertEqual(mimetypes.guess_extension('text/html'), '.html')
|
||||
self.assertEqual(mimetypes.guess_extension('text/plain'), '.txt')
|
||||
self.assertEqual(mimetypes.guess_extension('video/mpeg'), '.mpeg')
|
||||
self.assertEqual(mimetypes.guess_extension('video/quicktime'), '.mov')
|
||||
for mime_type, ext in (
|
||||
("application/epub+zip", ".epub"),
|
||||
("application/octet-stream", ".bin"),
|
||||
("application/gzip", ".gz"),
|
||||
("application/ogg", ".ogx"),
|
||||
("application/postscript", ".ps"),
|
||||
("application/vnd.apple.mpegurl", ".m3u"),
|
||||
("application/vnd.ms-excel", ".xls"),
|
||||
("application/vnd.ms-fontobject", ".eot"),
|
||||
("application/vnd.ms-powerpoint", ".ppt"),
|
||||
("application/vnd.oasis.opendocument.graphics", ".odg"),
|
||||
("application/vnd.oasis.opendocument.presentation", ".odp"),
|
||||
("application/vnd.oasis.opendocument.spreadsheet", ".ods"),
|
||||
("application/vnd.oasis.opendocument.text", ".odt"),
|
||||
("application/vnd.openxmlformats-officedocument.presentationml.presentation", ".pptx"),
|
||||
("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx"),
|
||||
("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx"),
|
||||
("application/vnd.rar", ".rar"),
|
||||
("application/x-7z-compressed", ".7z"),
|
||||
("application/x-debian-package", ".deb"),
|
||||
("application/x-httpd-php", ".php"),
|
||||
("application/x-rpm", ".rpm"),
|
||||
("application/x-texinfo", ".texi"),
|
||||
("application/x-troff", ".roff"),
|
||||
("application/xml", ".xsl"),
|
||||
("application/yaml", ".yaml"),
|
||||
("audio/flac", ".flac"),
|
||||
("audio/matroska", ".mka"),
|
||||
("audio/mp4", ".m4a"),
|
||||
("audio/mpeg", ".mp3"),
|
||||
("audio/ogg", ".ogg"),
|
||||
("audio/vnd.wave", ".wav"),
|
||||
("audio/webm", ".weba"),
|
||||
("font/otf", ".otf"),
|
||||
("font/ttf", ".ttf"),
|
||||
("font/woff", ".woff"),
|
||||
("font/woff2", ".woff2"),
|
||||
("image/avif", ".avif"),
|
||||
("image/emf", ".emf"),
|
||||
("image/fits", ".fits"),
|
||||
("image/g3fax", ".g3"),
|
||||
("image/jp2", ".jp2"),
|
||||
("image/jpeg", ".jpg"),
|
||||
("image/jpm", ".jpm"),
|
||||
("image/t38", ".t38"),
|
||||
("image/tiff", ".tiff"),
|
||||
("image/tiff-fx", ".tfx"),
|
||||
("image/webp", ".webp"),
|
||||
("image/wmf", ".wmf"),
|
||||
("message/rfc822", ".eml"),
|
||||
("model/gltf+json", ".gltf"),
|
||||
("model/gltf-binary", ".glb"),
|
||||
("model/stl", ".stl"),
|
||||
("text/html", ".html"),
|
||||
("text/plain", ".txt"),
|
||||
("text/rtf", ".rtf"),
|
||||
("text/x-rst", ".rst"),
|
||||
("video/matroska", ".mkv"),
|
||||
("video/matroska-3d", ".mk3d"),
|
||||
("video/mpeg", ".mpeg"),
|
||||
("video/ogg", ".ogv"),
|
||||
("video/quicktime", ".mov"),
|
||||
("video/vnd.avi", ".avi"),
|
||||
("video/x-m4v", ".m4v"),
|
||||
("video/x-ms-wmv", ".wmv"),
|
||||
):
|
||||
with self.subTest(mime_type=mime_type, ext=ext):
|
||||
self.assertEqual(mimetypes.guess_extension(mime_type), ext)
|
||||
|
||||
check_extensions()
|
||||
mimetypes.init()
|
||||
check_extensions()
|
||||
|
||||
def test_guess_file_type(self):
|
||||
def check_file_type():
|
||||
for mime_type, ext in (
|
||||
("application/yaml", ".yaml"),
|
||||
("application/yaml", ".yml"),
|
||||
("audio/mpeg", ".mp2"),
|
||||
("audio/mpeg", ".mp3"),
|
||||
("video/mpeg", ".m1v"),
|
||||
("video/mpeg", ".mpe"),
|
||||
("video/mpeg", ".mpeg"),
|
||||
("video/mpeg", ".mpg"),
|
||||
):
|
||||
with self.subTest(mime_type=mime_type, ext=ext):
|
||||
result, _ = mimetypes.guess_file_type(f"filename{ext}")
|
||||
self.assertEqual(result, mime_type)
|
||||
|
||||
check_file_type()
|
||||
mimetypes.init()
|
||||
check_file_type()
|
||||
|
||||
def test_init_stability(self):
|
||||
mimetypes.init()
|
||||
|
||||
@@ -189,27 +337,59 @@ class MimeTypesTestCase(unittest.TestCase):
|
||||
|
||||
def test_path_like_ob(self):
|
||||
filename = "LICENSE.txt"
|
||||
filepath = pathlib.Path(filename)
|
||||
filepath_with_abs_dir = pathlib.Path('/dir/'+filename)
|
||||
filepath_relative = pathlib.Path('../dir/'+filename)
|
||||
path_dir = pathlib.Path('./')
|
||||
filepath = os_helper.FakePath(filename)
|
||||
filepath_with_abs_dir = os_helper.FakePath('/dir/'+filename)
|
||||
filepath_relative = os_helper.FakePath('../dir/'+filename)
|
||||
path_dir = os_helper.FakePath('./')
|
||||
|
||||
expected = self.db.guess_type(filename)
|
||||
expected = self.db.guess_file_type(filename)
|
||||
|
||||
self.assertEqual(self.db.guess_file_type(filepath), expected)
|
||||
self.assertEqual(self.db.guess_type(filepath), expected)
|
||||
self.assertEqual(self.db.guess_file_type(
|
||||
filepath_with_abs_dir), expected)
|
||||
self.assertEqual(self.db.guess_type(
|
||||
filepath_with_abs_dir), expected)
|
||||
self.assertEqual(self.db.guess_file_type(filepath_relative), expected)
|
||||
self.assertEqual(self.db.guess_type(filepath_relative), expected)
|
||||
|
||||
self.assertEqual(self.db.guess_file_type(path_dir), (None, None))
|
||||
self.assertEqual(self.db.guess_type(path_dir), (None, None))
|
||||
|
||||
def test_bytes_path(self):
|
||||
self.assertEqual(self.db.guess_file_type(b'foo.html'),
|
||||
self.db.guess_file_type('foo.html'))
|
||||
self.assertEqual(self.db.guess_file_type(b'foo.tar.gz'),
|
||||
self.db.guess_file_type('foo.tar.gz'))
|
||||
self.assertEqual(self.db.guess_file_type(b'foo.tgz'),
|
||||
self.db.guess_file_type('foo.tgz'))
|
||||
|
||||
def test_keywords_args_api(self):
|
||||
self.assertEqual(self.db.guess_file_type(
|
||||
path="foo.html", strict=True), ("text/html", None))
|
||||
self.assertEqual(self.db.guess_type(
|
||||
url="foo.html", strict=True), ("text/html", None))
|
||||
url="scheme:foo.html", strict=True), ("text/html", None))
|
||||
self.assertEqual(self.db.guess_all_extensions(
|
||||
type='image/jpg', strict=True), [])
|
||||
self.assertEqual(self.db.guess_extension(
|
||||
type='image/jpg', strict=False), '.jpg')
|
||||
|
||||
def test_added_types_are_used(self):
|
||||
mimetypes.add_type('testing/default-type', '')
|
||||
mime_type, _ = mimetypes.guess_type('')
|
||||
self.assertEqual(mime_type, 'testing/default-type')
|
||||
|
||||
mime_type, _ = mimetypes.guess_type('test.myext')
|
||||
self.assertEqual(mime_type, None)
|
||||
|
||||
mimetypes.add_type('testing/type', '.myext')
|
||||
mime_type, _ = mimetypes.guess_type('test.myext')
|
||||
self.assertEqual(mime_type, 'testing/type')
|
||||
|
||||
def test_add_type_with_undotted_extension_deprecated(self):
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
mimetypes.add_type("testing/type", "undotted")
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith("win"), "Windows only")
|
||||
class Win32MimeTypesTestCase(unittest.TestCase):
|
||||
@@ -236,58 +416,94 @@ class Win32MimeTypesTestCase(unittest.TestCase):
|
||||
eq(self.db.guess_type("image.jpg"), ("image/jpeg", None))
|
||||
eq(self.db.guess_type("image.png"), ("image/png", None))
|
||||
|
||||
@unittest.skipIf(not hasattr(_winapi, "_mimetypes_read_windows_registry"),
|
||||
"read_windows_registry accelerator unavailable")
|
||||
def test_registry_accelerator(self):
|
||||
from_accel = {}
|
||||
from_reg = {}
|
||||
_winapi._mimetypes_read_windows_registry(
|
||||
lambda v, k: from_accel.setdefault(k, set()).add(v)
|
||||
)
|
||||
mimetypes.MimeTypes._read_windows_registry(
|
||||
lambda v, k: from_reg.setdefault(k, set()).add(v)
|
||||
)
|
||||
self.assertEqual(list(from_reg), list(from_accel))
|
||||
for k in from_reg:
|
||||
self.assertEqual(from_reg[k], from_accel[k])
|
||||
|
||||
|
||||
class MiscTestCase(unittest.TestCase):
|
||||
def test__all__(self):
|
||||
support.check__all__(self, mimetypes)
|
||||
|
||||
@cpython_only
|
||||
def test_lazy_import(self):
|
||||
ensure_lazy_imports("mimetypes", {"os", "posixpath", "urllib.parse", "argparse"})
|
||||
|
||||
class MimetypesCliTestCase(unittest.TestCase):
|
||||
|
||||
def mimetypes_cmd(self, *args, **kwargs):
|
||||
support.patch(self, sys, "argv", [sys.executable, *args])
|
||||
with support.captured_stdout() as output:
|
||||
mimetypes._main()
|
||||
return output.getvalue().strip()
|
||||
class CommandLineTest(unittest.TestCase):
|
||||
@force_not_colorized
|
||||
def test_parse_args(self):
|
||||
args, help_text = mimetypes._parse_args("-h")
|
||||
self.assertTrue(help_text.startswith("usage: "))
|
||||
|
||||
def test_help_option(self):
|
||||
support.patch(self, sys, "argv", [sys.executable, "-h"])
|
||||
with support.captured_stdout() as output:
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
mimetypes._main()
|
||||
args, help_text = mimetypes._parse_args("--invalid")
|
||||
self.assertTrue(help_text.startswith("usage: "))
|
||||
|
||||
self.assertIn("Usage: mimetypes.py", output.getvalue())
|
||||
self.assertEqual(cm.exception.code, 0)
|
||||
args, _ = mimetypes._parse_args(shlex.split("-l -e image/jpg"))
|
||||
self.assertTrue(args.extension)
|
||||
self.assertTrue(args.lenient)
|
||||
self.assertEqual(args.type, ["image/jpg"])
|
||||
|
||||
def test_invalid_option(self):
|
||||
support.patch(self, sys, "argv", [sys.executable, "--invalid"])
|
||||
with support.captured_stdout() as output:
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
mimetypes._main()
|
||||
args, _ = mimetypes._parse_args(shlex.split("-e image/jpg"))
|
||||
self.assertTrue(args.extension)
|
||||
self.assertFalse(args.lenient)
|
||||
self.assertEqual(args.type, ["image/jpg"])
|
||||
|
||||
self.assertIn("Usage: mimetypes.py", output.getvalue())
|
||||
self.assertEqual(cm.exception.code, 1)
|
||||
args, _ = mimetypes._parse_args(shlex.split("-l foo.webp"))
|
||||
self.assertFalse(args.extension)
|
||||
self.assertTrue(args.lenient)
|
||||
self.assertEqual(args.type, ["foo.webp"])
|
||||
|
||||
def test_guess_extension(self):
|
||||
eq = self.assertEqual
|
||||
args, _ = mimetypes._parse_args(shlex.split("foo.pic"))
|
||||
self.assertFalse(args.extension)
|
||||
self.assertFalse(args.lenient)
|
||||
self.assertEqual(args.type, ["foo.pic"])
|
||||
|
||||
extension = self.mimetypes_cmd("-l", "-e", "image/jpg")
|
||||
eq(extension, ".jpg")
|
||||
def test_multiple_inputs(self):
|
||||
result = "\n".join(mimetypes._main(shlex.split("foo.pdf foo.png")))
|
||||
self.assertEqual(
|
||||
result,
|
||||
"type: application/pdf encoding: None\n"
|
||||
"type: image/png encoding: None"
|
||||
)
|
||||
|
||||
extension = self.mimetypes_cmd("-e", "image/jpg")
|
||||
eq(extension, "I don't know anything about type image/jpg")
|
||||
def test_multiple_inputs_error(self):
|
||||
result = "\n".join(mimetypes._main(shlex.split("foo.pdf foo.bar_ext")))
|
||||
self.assertEqual(
|
||||
result,
|
||||
"type: application/pdf encoding: None\n"
|
||||
"error: media type unknown for foo.bar_ext"
|
||||
)
|
||||
|
||||
extension = self.mimetypes_cmd("-e", "image/jpeg")
|
||||
eq(extension, ".jpg")
|
||||
|
||||
def test_guess_type(self):
|
||||
eq = self.assertEqual
|
||||
def test_invocation(self):
|
||||
for command, expected in [
|
||||
("-l -e image/jpg", ".jpg"),
|
||||
("-e image/jpeg", ".jpg"),
|
||||
("-l foo.webp", "type: image/webp encoding: None"),
|
||||
]:
|
||||
result = "\n".join(mimetypes._main(shlex.split(command)))
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
type_info = self.mimetypes_cmd("-l", "foo.pic")
|
||||
eq(type_info, "type: image/pict encoding: None")
|
||||
|
||||
type_info = self.mimetypes_cmd("foo.pic")
|
||||
eq(type_info, "I don't know anything about type foo.pic")
|
||||
def test_invocation_error(self):
|
||||
for command, expected in [
|
||||
("-e image/jpg", "error: unknown type image/jpg"),
|
||||
("foo.bar_ext", "error: media type unknown for foo.bar_ext"),
|
||||
]:
|
||||
with self.subTest(command=command):
|
||||
result = "\n".join(mimetypes._main(shlex.split(command)))
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Vendored
+1
-1
@@ -3525,7 +3525,7 @@ class ThreadedTests(unittest.TestCase):
|
||||
else:
|
||||
s.close()
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON")
|
||||
def test_socketserver(self):
|
||||
"""Using socketserver to create and manage SSL connections."""
|
||||
server = make_https_server(self, certfile=SIGNED_CERTFILE)
|
||||
|
||||
Vendored
-1
@@ -727,7 +727,6 @@ def sanepathname2url(path):
|
||||
|
||||
class HandlerTests(unittest.TestCase, ExtraAssertions):
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: None != 'image/gif'
|
||||
def test_ftp(self):
|
||||
class MockFTPWrapper:
|
||||
def __init__(self, data):
|
||||
|
||||
Reference in new issue
Block a user