Skip to content

bpo-34926: Make mimetypes.guess_type accept os.PathLike objects #9777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 10, 2018
9 changes: 7 additions & 2 deletions Doc/library/mimetypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ the information :func:`init` sets up.

.. index:: pair: MIME; headers

Guess the type of a file based on its filename or URL, given by *url*. The
return value is a tuple ``(type, encoding)`` where *type* is ``None`` if the
Guess the type of a file based on its filename, path or URL, given by *url*.
URL can be a string or a :term:`path-like object`.

The return value is a tuple ``(type, encoding)`` where *type* is ``None`` if the
type can't be guessed (missing or unknown suffix) or a string of the form
``'type/subtype'``, usable for a MIME :mailheader:`content-type` header.

Expand All @@ -49,6 +51,9 @@ the information :func:`init` sets up.
*strict* is ``False``, some additional non-standard but commonly used MIME types
are also recognized.

.. versionchanged:: 3.8
Added support for url being a :term:`path-like object`.


.. function:: guess_all_extensions(type, strict=True)

Expand Down
3 changes: 2 additions & 1 deletion Lib/mimetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def add_type(self, type, ext, strict=True):
exts.append(ext)

def guess_type(self, url, strict=True):
"""Guess the type of a file based on its URL.
"""Guess the type of a file which is either a URL or a path-like object.

Return value is a tuple (type, encoding) where type is None if
the type can't be guessed (no or unknown suffix) or a string
Expand All @@ -113,6 +113,7 @@ def guess_type(self, url, strict=True):
Optional `strict' argument when False adds a bunch of commonly found,
but non-standard types.
"""
url = os.fspath(url)
scheme, url = urllib.parse._splittype(url)
if scheme == 'data':
# syntax of data URLs:
Expand Down
24 changes: 24 additions & 0 deletions Lib/test/test_mimetypes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io
import locale
import mimetypes
import pathlib
import sys
import unittest

Expand Down Expand Up @@ -77,6 +78,29 @@ def test_encoding(self):
strict=True)
self.assertEqual(exts, ['.g3', '.g\xb3'])

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('./')

expected = self.db.guess_type(filename)

self.assertEqual(self.db.guess_type(filepath), expected)
self.assertEqual(self.db.guess_type(
filepath_with_abs_dir), expected)
self.assertEqual(self.db.guess_type(filepath_relative), expected)
self.assertEqual(self.db.guess_type(path_dir), (None, None))

def test_keywords_args_api(self):
self.assertEqual(self.db.guess_type(
url="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')


@unittest.skipUnless(sys.platform.startswith("win"), "Windows only")
class Win32MimeTypesTestCase(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:meth:`mimetypes.MimeTypes.guess_type` now accepts :term:`path-like object` in addition to url strings.
Patch by Mayank Asthana.