| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -53,7 +53,7 @@ def main(): | |||
| 53 | 53 | # Guess the content type based on the file's extension. Encoding | |
| 54 | 54 | # will be ignored, although we should check for simple things like | |
| 55 | 55 | # gzip'd or compressed files. | |
| 56 | - ctype, encoding = mimetypes.guess_type(path) | ||
| 56 | + ctype, encoding = mimetypes.guess_file_type(path) | ||
| 57 | 57 | if ctype is None or encoding is not None: | |
| 58 | 58 | # No guess could be made, or the file is encoded (compressed), so | |
| 59 | 59 | # use a generic bag-of-bits type. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -52,7 +52,22 @@ the information :func:`init` sets up. | |||
| 52 | 52 | are also recognized. | |
| 53 | 53 | ||
| 54 | 54 | .. versionchanged:: 3.8 | |
| 55 | - Added support for url being a :term:`path-like object`. | ||
| 55 | + Added support for *url* being a :term:`path-like object`. | ||
| 56 | + | ||
| 57 | + .. deprecated:: 3.13 | ||
| 58 | + Passing a file path instead of URL is :term:`soft deprecated`. | ||
| 59 | + Use :func:`guess_file_type` for this. | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + .. function:: guess_file_type(path, *, strict=True) | ||
| 63 | + | ||
| 64 | + .. index:: pair: MIME; headers | ||
| 65 | + | ||
| 66 | + Guess the type of a file based on its path, given by *path*. | ||
| 67 | + Similar to the :func:`guess_type` function, but accepts a path instead of URL. | ||
| 68 | + Path can be a string, a bytes object or a :term:`path-like object`. | ||
| 69 | + | ||
| 70 | + .. versionadded:: 3.13 | ||
| 56 | 71 | ||
| 57 | 72 | ||
| 58 | 73 | .. function:: guess_all_extensions(type, strict=True) | |
@@ -61,7 +76,7 @@ the information :func:`init` sets up. | |||
| 61 | 76 | return value is a list of strings giving all possible filename extensions, | |
| 62 | 77 | including the leading dot (``'.'``). The extensions are not guaranteed to have | |
| 63 | 78 | been associated with any particular data stream, but would be mapped to the MIME | |
| 64 | - type *type* by :func:`guess_type`. | ||
| 79 | + type *type* by :func:`guess_type` and :func:`guess_file_type`. | ||
| 65 | 80 | ||
| 66 | 81 | The optional *strict* argument has the same meaning as with the :func:`guess_type` function. | |
| 67 | 82 | ||
@@ -72,8 +87,8 @@ the information :func:`init` sets up. | |||
| 72 | 87 | return value is a string giving a filename extension, including the leading dot | |
| 73 | 88 | (``'.'``). The extension is not guaranteed to have been associated with any | |
| 74 | 89 | particular data stream, but would be mapped to the MIME type *type* by | |
| 75 | - :func:`guess_type`. If no extension can be guessed for *type*, ``None`` is | ||
| 76 | - returned. | ||
| 90 | + :func:`guess_type` and :func:`guess_file_type`. | ||
| 91 | + If no extension can be guessed for *type*, ``None`` is returned. | ||
| 77 | 92 | ||
| 78 | 93 | The optional *strict* argument has the same meaning as with the :func:`guess_type` function. | |
| 79 | 94 | ||
@@ -238,6 +253,14 @@ than one MIME-type database; it provides an interface similar to the one of the | |||
| 238 | 253 | the object. | |
| 239 | 254 | ||
| 240 | 255 | ||
| 256 | + .. method:: MimeTypes.guess_file_type(path, *, strict=True) | ||
| 257 | + | ||
| 258 | + Similar to the :func:`guess_file_type` function, using the tables stored | ||
| 259 | + as part of the object. | ||
| 260 | + | ||
| 261 | + .. versionadded:: 3.13 | ||
| 262 | + | ||
| 263 | + | ||
| 241 | 264 | .. method:: MimeTypes.guess_all_extensions(type, strict=True) | |
| 242 | 265 | ||
| 243 | 266 | Similar to the :func:`guess_all_extensions` function, using the tables stored | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -865,7 +865,7 @@ directory and port number (default: 8000) on the command line:: | |||
| 865 | 865 | fn = os.path.join(path, environ["PATH_INFO"][1:]) | |
| 866 | 866 | if "." not in fn.split(os.path.sep)[-1]: | |
| 867 | 867 | fn = os.path.join(fn, "index.html") | |
| 868 | - mime_type = mimetypes.guess_type(fn)[0] | ||
| 868 | + mime_type = mimetypes.guess_file_type(fn)[0] | ||
| 869 | 869 | ||
| 870 | 870 | # Return 200 OK if file exists, otherwise 404 Not Found | |
| 871 | 871 | if os.path.exists(fn): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -623,6 +623,13 @@ math | |||
| 623 | 623 | "fusedMultiplyAdd" operation for special cases. | |
| 624 | 624 | (Contributed by Mark Dickinson and Victor Stinner in :gh:`73468`.) | |
| 625 | 625 | ||
| 626 | + mimetypes | ||
| 627 | + --------- | ||
| 628 | + | ||
| 629 | + * Add the :func:`~mimetypes.guess_file_type` function which works with file path. | ||
| 630 | + Passing file path instead of URL in :func:`~mimetypes.guess_type` is :term:`soft deprecated`. | ||
| 631 | + (Contributed by Serhiy Storchaka in :gh:`66543`.) | ||
| 632 | + | ||
| 626 | 633 | mmap | |
| 627 | 634 | ---- | |
| 628 | 635 | ||
@@ -1167,6 +1174,10 @@ Deprecated | |||
| 1167 | 1174 | ||
| 1168 | 1175 | .. Add deprecations above alphabetically, not here at the end. | |
| 1169 | 1176 | ||
| 1177 | + * Passing file path instead of URL in :func:`~mimetypes.guess_type` is :term:`soft deprecated`. | ||
| 1178 | + Use :func:`~mimetypes.guess_file_type` instead. | ||
| 1179 | + (Contributed by Serhiy Storchaka in :gh:`66543`.) | ||
| 1180 | + | ||
| 1170 | 1181 | Pending Removal in Python 3.14 | |
| 1171 | 1182 | ------------------------------ | |
| 1172 | 1183 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -897,7 +897,7 @@ def guess_type(self, path): | |||
| 897 | 897 | ext = ext.lower() | |
| 898 | 898 | if ext in self.extensions_map: | |
| 899 | 899 | return self.extensions_map[ext] | |
| 900 | - guess, _ = mimetypes.guess_type(path) | ||
| 900 | + guess, _ = mimetypes.guess_file_type(path) | ||
| 901 | 901 | if guess: | |
| 902 | 902 | return guess | |
| 903 | 903 | return 'application/octet-stream' | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,7 +40,7 @@ | |||
| 40 | 40 | ||
| 41 | 41 | __all__ = [ | |
| 42 | 42 | "knownfiles", "inited", "MimeTypes", | |
| 43 | - "guess_type", "guess_all_extensions", "guess_extension", | ||
| 43 | + "guess_type", "guess_file_type", "guess_all_extensions", "guess_extension", | ||
| 44 | 44 | "add_type", "init", "read_mime_types", | |
| 45 | 45 | "suffix_map", "encodings_map", "types_map", "common_types" | |
| 46 | 46 | ] | |
@@ -119,14 +119,14 @@ def guess_type(self, url, strict=True): | |||
| 119 | 119 | Optional `strict' argument when False adds a bunch of commonly found, | |
| 120 | 120 | but non-standard types. | |
| 121 | 121 | """ | |
| 122 | + # TODO: Deprecate accepting file paths (in particular path-like objects). | ||
| 122 | 123 | url = os.fspath(url) | |
| 123 | 124 | p = urllib.parse.urlparse(url) | |
| 124 | 125 | if p.scheme and len(p.scheme) > 1: | |
| 125 | 126 | scheme = p.scheme | |
| 126 | 127 | url = p.path | |
| 127 | 128 | else: | |
| 128 | - scheme = None | ||
| 129 | - url = os.path.splitdrive(url)[1] | ||
| 129 | + return self.guess_file_type(url, strict=strict) | ||
| 130 | 130 | if scheme == 'data': | |
| 131 | 131 | # syntax of data URLs: | |
| 132 | 132 | # dataurl := "data:" [ mediatype ] [ ";base64" ] "," data | |
@@ -146,13 +146,25 @@ def guess_type(self, url, strict=True): | |||
| 146 | 146 | if '=' in type or '/' not in type: | |
| 147 | 147 | type = 'text/plain' | |
| 148 | 148 | return type, None # never compressed, so encoding is None | |
| 149 | - base, ext = posixpath.splitext(url) | ||
| 149 | + return self._guess_file_type(url, strict, posixpath.splitext) | ||
| 150 | + | ||
| 151 | + def guess_file_type(self, path, *, strict=True): | ||
| 152 | + """Guess the type of a file based on its path. | ||
| 153 | + | ||
| 154 | + Similar to guess_type(), but takes file path istead of URL. | ||
| 155 | + """ | ||
| 156 | + path = os.fsdecode(path) | ||
| 157 | + path = os.path.splitdrive(path)[1] | ||
| 158 | + return self._guess_file_type(path, strict, os.path.splitext) | ||
| 159 | + | ||
| 160 | + def _guess_file_type(self, path, strict, splitext): | ||
| 161 | + base, ext = splitext(path) | ||
| 150 | 162 | while (ext_lower := ext.lower()) in self.suffix_map: | |
| 151 | - base, ext = posixpath.splitext(base + self.suffix_map[ext_lower]) | ||
| 163 | + base, ext = splitext(base + self.suffix_map[ext_lower]) | ||
| 152 | 164 | # encodings_map is case sensitive | |
| 153 | 165 | if ext in self.encodings_map: | |
| 154 | 166 | encoding = self.encodings_map[ext] | |
| 155 | - base, ext = posixpath.splitext(base) | ||
| 167 | + base, ext = splitext(base) | ||
| 156 | 168 | else: | |
| 157 | 169 | encoding = None | |
| 158 | 170 | ext = ext.lower() | |
@@ -310,6 +322,16 @@ def guess_type(url, strict=True): | |||
| 310 | 322 | return _db.guess_type(url, strict) | |
| 311 | 323 | ||
| 312 | 324 | ||
| 325 | + def guess_file_type(path, *, strict=True): | ||
| 326 | + """Guess the type of a file based on its path. | ||
| 327 | + | ||
| 328 | + Similar to guess_type(), but takes file path istead of URL. | ||
| 329 | + """ | ||
| 330 | + if _db is None: | ||
| 331 | + init() | ||
| 332 | + return _db.guess_file_type(path, strict=strict) | ||
| 333 | + | ||
| 334 | + | ||
| 313 | 335 | def guess_all_extensions(type, strict=True): | |
| 314 | 336 | """Guess the extensions for a file based on its MIME type. | |
| 315 | 337 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,20 +36,28 @@ def setUp(self): | |||
| 36 | 36 | ||
| 37 | 37 | def test_case_sensitivity(self): | |
| 38 | 38 | eq = self.assertEqual | |
| 39 | - eq(self.db.guess_type("foobar.HTML"), self.db.guess_type("foobar.html")) | ||
| 40 | - eq(self.db.guess_type("foobar.TGZ"), self.db.guess_type("foobar.tgz")) | ||
| 41 | - eq(self.db.guess_type("foobar.tar.Z"), ("application/x-tar", "compress")) | ||
| 42 | - eq(self.db.guess_type("foobar.tar.z"), (None, None)) | ||
| 39 | + eq(self.db.guess_file_type("foobar.html"), ("text/html", None)) | ||
| 40 | + eq(self.db.guess_type("scheme:foobar.html"), ("text/html", None)) | ||
| 41 | + eq(self.db.guess_file_type("foobar.HTML"), ("text/html", None)) | ||
| 42 | + eq(self.db.guess_type("scheme:foobar.HTML"), ("text/html", None)) | ||
| 43 | + eq(self.db.guess_file_type("foobar.tgz"), ("application/x-tar", "gzip")) | ||
| 44 | + eq(self.db.guess_type("scheme:foobar.tgz"), ("application/x-tar", "gzip")) | ||
| 45 | + eq(self.db.guess_file_type("foobar.TGZ"), ("application/x-tar", "gzip")) | ||
| 46 | + eq(self.db.guess_type("scheme:foobar.TGZ"), ("application/x-tar", "gzip")) | ||
| 47 | + eq(self.db.guess_file_type("foobar.tar.Z"), ("application/x-tar", "compress")) | ||
| 48 | + eq(self.db.guess_type("scheme:foobar.tar.Z"), ("application/x-tar", "compress")) | ||
| 49 | + eq(self.db.guess_file_type("foobar.tar.z"), (None, None)) | ||
| 50 | + eq(self.db.guess_type("scheme:foobar.tar.z"), (None, None)) | ||
| 43 | 51 | ||
| 44 | 52 | def test_default_data(self): | |
| 45 | 53 | eq = self.assertEqual | |
| 46 | - eq(self.db.guess_type("foo.html"), ("text/html", None)) | ||
| 47 | - eq(self.db.guess_type("foo.HTML"), ("text/html", None)) | ||
| 48 | - eq(self.db.guess_type("foo.tgz"), ("application/x-tar", "gzip")) | ||
| 49 | - eq(self.db.guess_type("foo.tar.gz"), ("application/x-tar", "gzip")) | ||
| 50 | - eq(self.db.guess_type("foo.tar.Z"), ("application/x-tar", "compress")) | ||
| 51 | - eq(self.db.guess_type("foo.tar.bz2"), ("application/x-tar", "bzip2")) | ||
| 52 | - eq(self.db.guess_type("foo.tar.xz"), ("application/x-tar", "xz")) | ||
| 54 | + eq(self.db.guess_file_type("foo.html"), ("text/html", None)) | ||
| 55 | + eq(self.db.guess_file_type("foo.HTML"), ("text/html", None)) | ||
| 56 | + eq(self.db.guess_file_type("foo.tgz"), ("application/x-tar", "gzip")) | ||
| 57 | + eq(self.db.guess_file_type("foo.tar.gz"), ("application/x-tar", "gzip")) | ||
| 58 | + eq(self.db.guess_file_type("foo.tar.Z"), ("application/x-tar", "compress")) | ||
| 59 | + eq(self.db.guess_file_type("foo.tar.bz2"), ("application/x-tar", "bzip2")) | ||
| 60 | + eq(self.db.guess_file_type("foo.tar.xz"), ("application/x-tar", "xz")) | ||
| 53 | 61 | ||
| 54 | 62 | def test_data_urls(self): | |
| 55 | 63 | eq = self.assertEqual | |
@@ -63,7 +71,7 @@ def test_file_parsing(self): | |||
| 63 | 71 | eq = self.assertEqual | |
| 64 | 72 | sio = io.StringIO("x-application/x-unittest pyunit\n") | |
| 65 | 73 | self.db.readfp(sio) | |
| 66 | - eq(self.db.guess_type("foo.pyunit"), | ||
| 74 | + eq(self.db.guess_file_type("foo.pyunit"), | ||
| 67 | 75 | ("x-application/x-unittest", None)) | |
| 68 | 76 | eq(self.db.guess_extension("x-application/x-unittest"), ".pyunit") | |
| 69 | 77 | ||
@@ -95,12 +103,12 @@ def test_read_mime_types(self): | |||
| 95 | 103 | def test_non_standard_types(self): | |
| 96 | 104 | eq = self.assertEqual | |
| 97 | 105 | # First try strict | |
| 98 | - eq(self.db.guess_type('foo.xul', strict=True), (None, None)) | ||
| 106 | + eq(self.db.guess_file_type('foo.xul', strict=True), (None, None)) | ||
| 99 | 107 | eq(self.db.guess_extension('image/jpg', strict=True), None) | |
| 100 | 108 | # And then non-strict | |
| 101 | - eq(self.db.guess_type('foo.xul', strict=False), ('text/xul', None)) | ||
| 102 | - eq(self.db.guess_type('foo.XUL', strict=False), ('text/xul', None)) | ||
| 103 | - eq(self.db.guess_type('foo.invalid', strict=False), (None, None)) | ||
| 109 | + eq(self.db.guess_file_type('foo.xul', strict=False), ('text/xul', None)) | ||
| 110 | + eq(self.db.guess_file_type('foo.XUL', strict=False), ('text/xul', None)) | ||
| 111 | + eq(self.db.guess_file_type('foo.invalid', strict=False), (None, None)) | ||
| 104 | 112 | eq(self.db.guess_extension('image/jpg', strict=False), '.jpg') | |
| 105 | 113 | eq(self.db.guess_extension('image/JPG', strict=False), '.jpg') | |
| 106 | 114 | ||
@@ -124,15 +132,26 @@ def test_filename_with_url_delimiters(self): | |||
| 124 | 132 | '//share/server/', '\\\\share\\server\\'): | |
| 125 | 133 | path = prefix + name | |
| 126 | 134 | with self.subTest(path=path): | |
| 135 | + eq(self.db.guess_file_type(path), gzip_expected) | ||
| 127 | 136 | eq(self.db.guess_type(path), gzip_expected) | |
| 128 | 137 | expected = (None, None) if os.name == 'nt' else gzip_expected | |
| 129 | 138 | for prefix in ('//', '\\\\', '//share/', '\\\\share\\'): | |
| 130 | 139 | path = prefix + name | |
| 131 | 140 | with self.subTest(path=path): | |
| 141 | + eq(self.db.guess_file_type(path), expected) | ||
| 132 | 142 | eq(self.db.guess_type(path), expected) | |
| 143 | + eq(self.db.guess_file_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected) | ||
| 133 | 144 | eq(self.db.guess_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected) | |
| 134 | 145 | ||
| 146 | + eq(self.db.guess_file_type(r'foo/.tar.gz'), (None, 'gzip')) | ||
| 147 | + eq(self.db.guess_type(r'foo/.tar.gz'), (None, 'gzip')) | ||
| 148 | + expected = (None, 'gzip') if os.name == 'nt' else gzip_expected | ||
| 149 | + eq(self.db.guess_file_type(r'foo\.tar.gz'), expected) | ||
| 150 | + eq(self.db.guess_type(r'foo\.tar.gz'), expected) | ||
| 151 | + eq(self.db.guess_type(r'scheme:foo\.tar.gz'), gzip_expected) | ||
| 152 | + | ||
| 135 | 153 | def test_url(self): | |
| 154 | + result = self.db.guess_type('http://example.com/host.html') | ||
| 136 | 155 | result = self.db.guess_type('http://host.html') | |
| 137 | 156 | msg = 'URL only has a host name, not a file' | |
| 138 | 157 | self.assertSequenceEqual(result, (None, None), msg) | |
@@ -242,22 +261,38 @@ def test_init_stability(self): | |||
| 242 | 261 | ||
| 243 | 262 | def test_path_like_ob(self): | |
| 244 | 263 | filename = "LICENSE.txt" | |
| 245 | - filepath = pathlib.Path(filename) | ||
| 246 | - filepath_with_abs_dir = pathlib.Path('/dir/'+filename) | ||
| 247 | - filepath_relative = pathlib.Path('../dir/'+filename) | ||
| 248 | - path_dir = pathlib.Path('./') | ||
| 264 | + filepath = os_helper.FakePath(filename) | ||
| 265 | + filepath_with_abs_dir = os_helper.FakePath('/dir/'+filename) | ||
| 266 | + filepath_relative = os_helper.FakePath('../dir/'+filename) | ||
| 267 | + path_dir = os_helper.FakePath('./') | ||
| 249 | 268 | ||
| 250 | - expected = self.db.guess_type(filename) | ||
| 269 | + expected = self.db.guess_file_type(filename) | ||
| 251 | 270 | ||
| 271 | + self.assertEqual(self.db.guess_file_type(filepath), expected) | ||
| 252 | 272 | self.assertEqual(self.db.guess_type(filepath), expected) | |
| 273 | + self.assertEqual(self.db.guess_file_type( | ||
| 274 | + filepath_with_abs_dir), expected) | ||
| 253 | 275 | self.assertEqual(self.db.guess_type( | |
| 254 | 276 | filepath_with_abs_dir), expected) | |
| 277 | + self.assertEqual(self.db.guess_file_type(filepath_relative), expected) | ||
| 255 | 278 | self.assertEqual(self.db.guess_type(filepath_relative), expected) | |
| 279 | + | ||
| 280 | + self.assertEqual(self.db.guess_file_type(path_dir), (None, None)) | ||
| 256 | 281 | self.assertEqual(self.db.guess_type(path_dir), (None, None)) | |
| 257 | 282 | ||
| 283 | + def test_bytes_path(self): | ||
| 284 | + self.assertEqual(self.db.guess_file_type(b'foo.html'), | ||
| 285 | + self.db.guess_file_type('foo.html')) | ||
| 286 | + self.assertEqual(self.db.guess_file_type(b'foo.tar.gz'), | ||
| 287 | + self.db.guess_file_type('foo.tar.gz')) | ||
| 288 | + self.assertEqual(self.db.guess_file_type(b'foo.tgz'), | ||
| 289 | + self.db.guess_file_type('foo.tgz')) | ||
| 290 | + | ||
| 258 | 291 | def test_keywords_args_api(self): | |
| 292 | + self.assertEqual(self.db.guess_file_type( | ||
| 293 | + path="foo.html", strict=True), ("text/html", None)) | ||
| 259 | 294 | self.assertEqual(self.db.guess_type( | |
| 260 | - url="foo.html", strict=True), ("text/html", None)) | ||
| 295 | + url="scheme:foo.html", strict=True), ("text/html", None)) | ||
| 261 | 296 | self.assertEqual(self.db.guess_all_extensions( | |
| 262 | 297 | type='image/jpg', strict=True), []) | |
| 263 | 298 | self.assertEqual(self.db.guess_extension( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + Add the :func:`mimetypes.guess_file_type` function which works with file | ||
| 2 | + path. Passing file path instead of URL in :func:`~mimetypes.guess_type` is | ||
| 3 | + :term:`soft deprecated`. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments