Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions Lib/mimetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
read_mime_types(file) -- parse one file, return a dictionary or None
"""

lazy import os
lazy import posixpath
lazy import urllib.parse

try:
from _winapi import _mimetypes_read_windows_registry
except ImportError:
Expand Down Expand Up @@ -121,12 +125,13 @@ def guess_type(self, url, strict=True):
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)
# Without a ':' the argument cannot carry a URL scheme, so it cannot
# be a URL; skip the relatively expensive urlparse() in that case.
if isinstance(url, str) and ':' not in url:
return self.guess_file_type(url, strict=strict)
Comment thread
gaborbernat marked this conversation as resolved.

p = urllib.parse.urlparse(url)
if p.scheme and len(p.scheme) > 1:
scheme = p.scheme
Expand All @@ -153,19 +158,13 @@ def guess_type(self, url, strict=True):
type = 'text/plain'
return type, None # never compressed, so encoding is None

# 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)
Expand Down Expand Up @@ -412,9 +411,6 @@ 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)
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_mimetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,15 @@ def test_url(self):
result = self.db.guess_type('http://example.com/host.html?q=x.tar')
self.assertSequenceEqual(result, ('text/html', None))

def test_path_with_colon_but_no_url_scheme(self):
# A ':' that does not introduce a real URL scheme -- a single-letter
# Windows drive, or a colon elsewhere in the name -- is treated as a
# file path rather than a URL.
eq = self.assertSequenceEqual
eq(self.db.guess_type("c:fake.html"), ("text/html", None))
eq(self.db.guess_type(r"c:\dir\fake.html"), ("text/html", None))
eq(self.db.guess_type("note 12:30.txt"), ("text/plain", None))

def test_guess_all_types(self):
# First try strict. Use a set here for testing the results because if
# test_urllib2 is run before test_mimetypes, global state is modified
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Speed up :func:`mimetypes.guess_type` for plain file paths by skipping URL
parsing when the argument has no scheme. Patch by Bernát Gábor.
Loading