Skip to content

Commit 1788ed3

Browse files
gh-151575: Emit DeprecationWarning in mimetypes.guess_type() for file paths
1 parent 9e863fa commit 1788ed3

6 files changed

Lines changed: 122 additions & 5 deletions

File tree

Doc/deprecations/pending-removal-in-future.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ although there is currently no date scheduled for their removal.
7575
* :mod:`mailbox`: Use of StringIO input and text mode is deprecated, use
7676
BytesIO and binary mode instead.
7777

78+
* :mod:`mimetypes`: Passing a file path (including path-like objects and bytes
79+
paths) to :func:`~mimetypes.guess_type`. Use
80+
:func:`~mimetypes.guess_file_type` instead. (:gh:`151575`)
81+
7882
* :mod:`os`: Calling :func:`os.register_at_fork` in a multi-threaded process.
7983

8084
* :mod:`os.path`: :func:`os.path.commonprefix` is deprecated, use

Doc/library/mimetypes.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ the information :func:`init` sets up.
5454
.. versionchanged:: 3.8
5555
Added support for *url* being a :term:`path-like object`.
5656

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

6161

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

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

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

Doc/whatsnew/3.16.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,13 @@ Deprecated
271271
3.9, now issues a deprecation warning on use. This property is slated for
272272
removal in 3.21. Use ``ast.Tuple.elts`` instead.
273273

274+
* :mod:`mimetypes`:
275+
276+
* Passing a file path (or :term:`path-like object`) to
277+
:func:`mimetypes.guess_type` is now deprecated.
278+
Use :func:`mimetypes.guess_file_type` instead.
279+
(Contributed by Naveen Kumar G in :gh:`151575`.)
280+
274281
.. Add deprecations above alphabetically, not here at the end.
275282
276283
.. include:: ../deprecations/pending-removal-in-3.17.rst

Lib/mimetypes.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ def add_type(self, type, ext, strict=True):
106106
exts.append(ext)
107107

108108
def guess_type(self, url, strict=True):
109-
"""Guess the type of a file which is either a URL or a path-like object.
109+
"""Guess the type of a file based on its URL.
110+
111+
.. deprecated:: 3.16
112+
Passing a file path (or path-like object) is deprecated.
113+
Use :meth:`guess_file_type` instead.
110114
111115
Return value is a tuple (type, encoding) where type is None if
112116
the type can't be guessed (no or unknown suffix) or a string
@@ -127,14 +131,21 @@ def guess_type(self, url, strict=True):
127131
# Lazy import to improve module import time
128132
import os
129133
import urllib.parse
134+
import warnings
130135

131-
# TODO: Deprecate accepting file paths (in particular path-like objects).
132136
url = os.fspath(url)
133137
p = urllib.parse.urlparse(url)
134138
if p.scheme and len(p.scheme) > 1:
135139
scheme = p.scheme
136140
url = p.path
137141
else:
142+
# Input has no URL scheme — it is a file path, not a URL.
143+
warnings.warn(
144+
"Passing a file path to guess_type() is deprecated and will be "
145+
"removed in a future version. Use guess_file_type() instead.",
146+
DeprecationWarning,
147+
stacklevel=2,
148+
)
138149
return self.guess_file_type(url, strict=strict)
139150
if scheme == 'data':
140151
# syntax of data URLs:

Lib/test/test_mimetypes.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import io
22
import mimetypes
33
import os
4+
import pathlib
45
import shlex
56
import sys
7+
import unittest
68
import unittest.mock
9+
import warnings
710
from platform import win32_edition
811
from test import support
912
from test.support import cpython_only, force_not_colorized, os_helper, requires_subprocess
@@ -489,6 +492,94 @@ def test_keywords_args_api(self):
489492
type='image/jpeg', strict=True), ['.jpg', '.jpe', '.jpeg'])
490493

491494

495+
class GuessTypeDeprecationTestCase(unittest.TestCase):
496+
"""Tests that guess_type() emits DeprecationWarning for file path inputs."""
497+
498+
def setUp(self):
499+
self.db = mimetypes.MimeTypes()
500+
501+
# --- Module-level function tests ---
502+
503+
def test_module_plain_string_path_warns(self):
504+
"""Module-level guess_type() warns for a plain string with no URL scheme."""
505+
with self.assertWarns(DeprecationWarning) as cm:
506+
mimetypes.guess_type("file.txt")
507+
self.assertIn("guess_file_type", str(cm.warning))
508+
self.assertIn("deprecated", str(cm.warning).lower())
509+
510+
def test_module_pathlike_warns(self):
511+
"""Module-level guess_type() warns for a path-like object."""
512+
with self.assertWarns(DeprecationWarning):
513+
mimetypes.guess_type(pathlib.Path("file.txt"))
514+
515+
def test_module_bytes_path_warns(self):
516+
"""Module-level guess_type() warns for a bytes path."""
517+
with self.assertWarns(DeprecationWarning):
518+
mimetypes.guess_type(b"file.txt")
519+
520+
def test_module_url_with_scheme_no_warning(self):
521+
"""Module-level guess_type() does NOT warn for a proper URL."""
522+
with warnings.catch_warnings():
523+
warnings.simplefilter("error", DeprecationWarning)
524+
# Should not raise -- http:// is a valid multi-char scheme.
525+
mimetypes.guess_type("http://example.com/file.html")
526+
527+
def test_module_data_url_no_warning(self):
528+
"""Module-level guess_type() does NOT warn for data: URLs."""
529+
with warnings.catch_warnings():
530+
warnings.simplefilter("error", DeprecationWarning)
531+
mimetypes.guess_type("data:text/plain,hello")
532+
533+
# --- MimeTypes class method tests ---
534+
535+
def test_method_plain_string_path_warns(self):
536+
"""MimeTypes.guess_type() warns for a plain string with no URL scheme."""
537+
with self.assertWarns(DeprecationWarning) as cm:
538+
self.db.guess_type("file.html")
539+
self.assertIn("guess_file_type", str(cm.warning))
540+
541+
def test_method_pathlike_warns(self):
542+
"""MimeTypes.guess_type() warns for a path-like object."""
543+
with self.assertWarns(DeprecationWarning):
544+
self.db.guess_type(pathlib.Path("file.html"))
545+
546+
def test_method_bytes_path_warns(self):
547+
"""MimeTypes.guess_type() warns for a bytes path."""
548+
with self.assertWarns(DeprecationWarning):
549+
self.db.guess_type(b"file.html")
550+
551+
def test_method_url_with_scheme_no_warning(self):
552+
"""MimeTypes.guess_type() does NOT warn for a proper URL."""
553+
with warnings.catch_warnings():
554+
warnings.simplefilter("error", DeprecationWarning)
555+
self.db.guess_type("http://example.com/file.html")
556+
557+
def test_method_ftp_url_no_warning(self):
558+
"""MimeTypes.guess_type() does NOT warn for an ftp: URL."""
559+
with warnings.catch_warnings():
560+
warnings.simplefilter("error", DeprecationWarning)
561+
self.db.guess_type("ftp://example.com/file.tar.gz")
562+
563+
def test_result_unchanged(self):
564+
"""guess_type() with a file path still returns the correct MIME type."""
565+
with self.assertWarns(DeprecationWarning):
566+
result = mimetypes.guess_type("file.html")
567+
expected = mimetypes.guess_file_type("file.html")
568+
self.assertEqual(result, expected)
569+
570+
def test_result_unchanged_pathlike(self):
571+
"""guess_type() with a PathLike still returns the correct MIME type."""
572+
with self.assertWarns(DeprecationWarning):
573+
result = self.db.guess_type(pathlib.Path("file.tar.gz"))
574+
expected = self.db.guess_file_type(pathlib.Path("file.tar.gz"))
575+
self.assertEqual(result, expected)
576+
577+
def test_os_helper_fakepath_warns(self):
578+
"""guess_type() warns for os_helper.FakePath (a path-like object)."""
579+
with self.assertWarns(DeprecationWarning):
580+
self.db.guess_type(os_helper.FakePath("file.tar.gz"))
581+
582+
492583
@unittest.skipUnless(sys.platform.startswith("win"), "Windows only")
493584
class Win32MimeTypesTestCase(unittest.TestCase):
494585
def setUp(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Emit DeprecationWarning when a file path is passed to :func:`mimetypes.guess_type`. Use :func:`mimetypes.guess_file_type` instead.

0 commit comments

Comments
 (0)