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
4 changes: 4 additions & 0 deletions Doc/deprecations/pending-removal-in-future.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ although there is currently no date scheduled for their removal.
* :mod:`mailbox`: Use of StringIO input and text mode is deprecated, use
BytesIO and binary mode instead.

* :mod:`mimetypes`: Passing a file path (including path-like objects and bytes
paths) to :func:`~mimetypes.guess_type`. Use
:func:`~mimetypes.guess_file_type` instead. (:gh:`151575`)

* :mod:`os`: Calling :func:`os.register_at_fork` in a multi-threaded process.

* :mod:`os.path`: :func:`os.path.commonprefix` is deprecated, use
Expand Down
9 changes: 6 additions & 3 deletions Doc/library/mimetypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ the information :func:`init` sets up.
.. versionchanged:: 3.8
Added support for *url* being a :term:`path-like object`.

.. soft-deprecated:: 3.13
Passing a file path instead of URL.
Use :func:`guess_file_type` for this.
.. deprecated:: 3.16
Passing a file path (or path-like object) instead of a URL.
Use :func:`guess_file_type` instead.


.. function:: guess_file_type(path, *, strict=True)
Expand Down Expand Up @@ -262,6 +262,9 @@ than one MIME-type database; it provides an interface similar to the one of the
Similar to the :func:`guess_type` function, using the tables stored as part of
the object.

.. deprecated:: 3.16
Passing a file path (or path-like object) instead of a URL.
Use :meth:`guess_file_type` instead.

.. method:: MimeTypes.guess_file_type(path, *, strict=True)

Expand Down
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,13 @@ Deprecated
3.9, now issues a deprecation warning on use. This property is slated for
removal in 3.21. Use ``ast.Tuple.elts`` instead.

* :mod:`mimetypes`:

* Passing a file path (or :term:`path-like object`) to
:func:`mimetypes.guess_type` is now deprecated.
Use :func:`mimetypes.guess_file_type` instead.
(Contributed by Naveen Kumar G in :gh:`151575`.)

.. Add deprecations above alphabetically, not here at the end.
.. include:: ../deprecations/pending-removal-in-3.17.rst
Expand Down
15 changes: 13 additions & 2 deletions Lib/mimetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ def add_type(self, type, ext, strict=True):
exts.append(ext)

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

.. deprecated:: 3.16
Passing a file path (or path-like object) is deprecated.
Use :meth:`guess_file_type` instead.

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 @@ -127,14 +131,21 @@ def guess_type(self, url, strict=True):
# Lazy import to improve module import time
import os
import urllib.parse
import warnings

# TODO: Deprecate accepting file paths (in particular path-like objects).
url = os.fspath(url)
p = urllib.parse.urlparse(url)
if p.scheme and len(p.scheme) > 1:
scheme = p.scheme
url = p.path
else:
# Input has no URL scheme — it is a file path, not a URL.
warnings.warn(
"Passing a file path to guess_type() is deprecated and will be "
"removed in a future version. Use guess_file_type() instead.",
DeprecationWarning,
stacklevel=2,
)
return self.guess_file_type(url, strict=strict)
if scheme == 'data':
# syntax of data URLs:
Expand Down
91 changes: 91 additions & 0 deletions Lib/test/test_mimetypes.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import io
import mimetypes
import os
import pathlib
import shlex
import sys
import unittest
import unittest.mock
import warnings
from platform import win32_edition
from test import support
from test.support import cpython_only, force_not_colorized, os_helper, requires_subprocess
Expand Down Expand Up @@ -489,6 +492,94 @@ def test_keywords_args_api(self):
type='image/jpeg', strict=True), ['.jpg', '.jpe', '.jpeg'])


class GuessTypeDeprecationTestCase(unittest.TestCase):
"""Tests that guess_type() emits DeprecationWarning for file path inputs."""

def setUp(self):
self.db = mimetypes.MimeTypes()

# --- Module-level function tests ---

def test_module_plain_string_path_warns(self):
"""Module-level guess_type() warns for a plain string with no URL scheme."""
with self.assertWarns(DeprecationWarning) as cm:
mimetypes.guess_type("file.txt")
self.assertIn("guess_file_type", str(cm.warning))
self.assertIn("deprecated", str(cm.warning).lower())

def test_module_pathlike_warns(self):
"""Module-level guess_type() warns for a path-like object."""
with self.assertWarns(DeprecationWarning):
mimetypes.guess_type(pathlib.Path("file.txt"))

def test_module_bytes_path_warns(self):
"""Module-level guess_type() warns for a bytes path."""
with self.assertWarns(DeprecationWarning):
mimetypes.guess_type(b"file.txt")

def test_module_url_with_scheme_no_warning(self):
"""Module-level guess_type() does NOT warn for a proper URL."""
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
# Should not raise -- http:// is a valid multi-char scheme.
mimetypes.guess_type("http://example.com/file.html")

def test_module_data_url_no_warning(self):
"""Module-level guess_type() does NOT warn for data: URLs."""
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
mimetypes.guess_type("data:text/plain,hello")

# --- MimeTypes class method tests ---

def test_method_plain_string_path_warns(self):
"""MimeTypes.guess_type() warns for a plain string with no URL scheme."""
with self.assertWarns(DeprecationWarning) as cm:
self.db.guess_type("file.html")
self.assertIn("guess_file_type", str(cm.warning))

def test_method_pathlike_warns(self):
"""MimeTypes.guess_type() warns for a path-like object."""
with self.assertWarns(DeprecationWarning):
self.db.guess_type(pathlib.Path("file.html"))

def test_method_bytes_path_warns(self):
"""MimeTypes.guess_type() warns for a bytes path."""
with self.assertWarns(DeprecationWarning):
self.db.guess_type(b"file.html")

def test_method_url_with_scheme_no_warning(self):
"""MimeTypes.guess_type() does NOT warn for a proper URL."""
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
self.db.guess_type("http://example.com/file.html")

def test_method_ftp_url_no_warning(self):
"""MimeTypes.guess_type() does NOT warn for an ftp: URL."""
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
self.db.guess_type("ftp://example.com/file.tar.gz")

def test_result_unchanged(self):
"""guess_type() with a file path still returns the correct MIME type."""
with self.assertWarns(DeprecationWarning):
result = mimetypes.guess_type("file.html")
expected = mimetypes.guess_file_type("file.html")
self.assertEqual(result, expected)

def test_result_unchanged_pathlike(self):
"""guess_type() with a PathLike still returns the correct MIME type."""
with self.assertWarns(DeprecationWarning):
result = self.db.guess_type(pathlib.Path("file.tar.gz"))
expected = self.db.guess_file_type(pathlib.Path("file.tar.gz"))
self.assertEqual(result, expected)

def test_os_helper_fakepath_warns(self):
"""guess_type() warns for os_helper.FakePath (a path-like object)."""
with self.assertWarns(DeprecationWarning):
self.db.guess_type(os_helper.FakePath("file.tar.gz"))


@unittest.skipUnless(sys.platform.startswith("win"), "Windows only")
class Win32MimeTypesTestCase(unittest.TestCase):
def setUp(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Emit DeprecationWarning when a file path is passed to :func:`mimetypes.guess_type`. Use :func:`mimetypes.guess_file_type` instead.
Loading