Skip to content

gh-151575: Deprecate passing file paths instead of URLs to mimetypes.guess_type() - #151576

Open
NaveenKumarG-dev wants to merge 13 commits into
python:mainfrom
NaveenKumarG-dev:gh-mimetypes-guess-type-deprecation
Open

gh-151575: Deprecate passing file paths instead of URLs to mimetypes.guess_type()#151576
NaveenKumarG-dev wants to merge 13 commits into
python:mainfrom
NaveenKumarG-dev:gh-mimetypes-guess-type-deprecation

Conversation

@NaveenKumarG-dev

@NaveenKumarG-dev NaveenKumarG-dev commented Jun 17, 2026

Copy link
Copy Markdown

Context

mimetypes.guess_type() is intended for URLs, while mimetypes.guess_file_type() was introduced in Python 3.13 as the preferred API for file paths.

The implementation still accepts file paths without warning, despite the existing # TODO: Deprecate accepting file paths (in particular path-like objects) comment in Lib/mimetypes.py. This PR implements that TODO by deprecating file path inputs to guess_type() and directing users to guess_file_type() instead.

Changes Made

  • Implementation: Modified mimetypes.MimeTypes.guess_type() to emit a DeprecationWarning (stacklevel=2) when called with a file path instead of a URL.

  • Coverage: The warning triggers for plain strings that do not contain a valid URL scheme, as well as for bytes and os.PathLike objects. Valid URLs such as http://, ftp://, and data: continue to behave as before.

  • Testing: Added GuessTypeDeprecationTestCase to Lib/test/test_mimetypes.py covering path and URL inputs to verify warning behavior and prevent regressions.

  • Documentation:

    • Updated Doc/library/mimetypes.rst to document the runtime deprecation.
    • Added entries to Doc/whatsnew/3.16.rst and Doc/deprecations/pending-removal-in-future.rst.
  • NEWS: Added the required NEWS entry using blurb.

Rationale

This change aligns the runtime behavior with the documented distinction between URL handling (guess_type()) and file-path handling (guess_file_type()), while implementing the existing deprecation TODO in the source code.

Linked Issue

Fixes #151575


Code of Conduct and CLA

  • I have read the Python Developer's Guide
  • I have read the Python Code of Conduct
  • I have signed the Contributor License Agreement (CLA)

@read-the-docs-community

read-the-docs-community Bot commented Jun 17, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33453444 | 📁 Comparing ec6e1da against main (9e863fa)

  🔍 Preview build  

84 files changed · ± 83 modified · - 1 deleted

± Modified

- Deleted

@NaveenKumarG-dev NaveenKumarG-dev changed the title gh-151575: Emit DeprecationWarning in mimetypes.guess_type() for file… gh-151575: Deprecate passing file paths instead of URLs to mimetypes.guess_type() Jun 17, 2026
Comment thread Doc/library/mimetypes.rst
.. soft-deprecated:: 3.13
Passing a file path instead of URL.
Use :func:`guess_file_type` for this.
.. deprecated:: 3.16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Schedule removal for Python 3.21. Also, please add a note that it was soft-deprecated since Python 3.13.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these "scheduled for removal" notes should be in Doc/deprecations/pending-removal-in-3.21.rst, not inline in all of the various notes. @NaveenKumarG-dev, could you move them over to there? You'll see some examples of other pending items in that doc directory.

@StanFromIreland, is it right to include a note about the soft-deprecated history? I don't see that on other deprecations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these "scheduled for removal" notes should be in Doc/deprecations/pending-removal-in-3.21.rst, not inline in all of the various notes.

I would prefer we have them here as well, that's our usual process. Otherwise, how is a user meant to know whether the function is going away, compared to just a subset of its functionality?

@StanFromIreland, is it right to include a note about the soft-deprecated history? I don't see that on other deprecations.

Let's include it for clarity. (And that's probably because they weren't soft-deprecated before, it's quite rare to do this.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Schedule removal for Python 3.21.

Suggested change
.. deprecated:: 3.16
.. deprecated-removed:: 3.16 3.21

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer we have them here as well, that's our usual process.

Oh, now that I'm looking more carefully and tracing this back, this is my mistake! Your statement that this is the norm made me recheck things, and I now see that we have a dedicated directive for this, deprecated-removed.

I believe that the correct course of action here is to update all of these to use deprecated-removed:: 3.16 3.21.

The text which is added here, stating the removal plan, is not typical, and I think should be removed.


Does the soft-deprecation need to be a textual note, or should it be simply a set of stacked directives, like so?

.. soft-deprecated:: 3.13

.. deprecated-removed:: 3.16 3.21
    text goes here

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, sorry Stephen, I may be misunderstanding, do you want them to remove the entire note under the directive? We need to be clear about what we're removing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting aside my earlier mistake, I think the correct rewrite is to remove the part of the note which details soft-deprecation and removal schedule, and use the directives instead.

So the rewrite should be something like this:

-  .. deprecated:: 3.16
+  .. soft-deprecated:: 3.13
+  .. deprecated-removed:: 3.16 3.21
          Passing a file path (or path-like object) instead of a URL.
          Use :meth:`guess_file_type` instead.
-         Soft-deprecated since Python 3.13, scheduled for removal in Python 3.21.

Comment thread Doc/library/mimetypes.rst Outdated
Comment on lines 31 to 32

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also remove file paths/path-like objects here.

Comment thread Lib/test/test_mimetypes.py Outdated
type='image/jpeg', strict=True), ['.jpg', '.jpe', '.jpeg'])


class GuessTypeDeprecationTestCase(unittest.TestCase):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already covered above, I don't see anything that adds new coverage? We also run our test suite with -Werror on buildbots, so we don't miss spurious warnings.

Comment thread Lib/mimetypes.py Outdated
"""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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this note.

Comment thread Lib/mimetypes.py Outdated
scheme = p.scheme
url = p.path
else:
# Input has no URL scheme — it is a file path, not a URL.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Input has no URL scheme — it is a file path, not a URL.

I think it's sufficiently clear from reading the logic, let's not repeat ourselves.

@@ -0,0 +1 @@
Emit DeprecationWarning when a file path is passed to :func:`mimetypes.guess_type`. Use :func:`mimetypes.guess_file_type` instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reword it like so please: "Deprecate passing X to X. Use X instead."

@StanFromIreland

Copy link
Copy Markdown
Member

Please do not use the Update Branch button unless necessary (e.g. fixing conflicts, jogging the CI, or very old PRs) as it uses valuable resources and results in spurious notifications. For more information see the devguide.

Comment thread Doc/library/mimetypes.rst
Comment on lines +31 to +32
Guess the type of a file based on its URL, given by *url*.
URL can be a string.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change seems malformed. "URL can be a string." isn't a normal sentence to have in docs.

I suggest:

Suggested change
Guess the type of a file based on its URL, given by *url*.
URL can be a string.
Guess the type of a file based on its URL, given as a string.

Comment thread Doc/library/mimetypes.rst
.. soft-deprecated:: 3.13
Passing a file path instead of URL.
Use :func:`guess_file_type` for this.
.. deprecated:: 3.16

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these "scheduled for removal" notes should be in Doc/deprecations/pending-removal-in-3.21.rst, not inline in all of the various notes. @NaveenKumarG-dev, could you move them over to there? You'll see some examples of other pending items in that doc directory.

@StanFromIreland, is it right to include a note about the soft-deprecated history? I don't see that on other deprecations.

Comment thread Lib/mimetypes.py
else:
for gtype in args.type:
guess, encoding = guess_type(gtype, not args.lenient)
guess, encoding = guess_file_type(gtype, strict=not args.lenient)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes behavior in a way I wouldn't consider safe.

guess_type has capabilities that guess_file_type does not. For example, it can read data URLs:

$ python -m mimetypes 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ=='
type: text/plain encoding: None

I think the simplest thing to do here is to repeat the urllib.parse.urlparse and scheme check that guess_type currently includes. That way, CLI usage can switch between guess_type and guess_file_type safely.

import io
import mimetypes
import os

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert these unrelated changes.

Comment thread Lib/mimetypes.py
# Lazy import to improve module import time
import os
import urllib.parse
import warnings

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use lazy import (and you can move the others as well).

Comment thread Doc/library/mimetypes.rst
.. soft-deprecated:: 3.13
Passing a file path instead of URL.
Use :func:`guess_file_type` for this.
.. deprecated:: 3.16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Schedule removal for Python 3.21.

Suggested change
.. deprecated:: 3.16
.. deprecated-removed:: 3.16 3.21

Comment thread Doc/library/mimetypes.rst
Similar to the :func:`guess_type` function, using the tables stored as part of
the object.

.. deprecated:: 3.16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.. deprecated:: 3.16
.. deprecated-removed:: 3.16 3.21

Comment thread Doc/library/mimetypes.rst
.. deprecated:: 3.16
Passing a file path (or path-like object) instead of a URL.
Use :func:`guess_file_type` instead.
Soft-deprecated since Python 3.13, scheduled for removal in Python 3.21.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can skip this if we keep the .. soft-deprecated:: 3.13 bit and use .. deprecated-removed:: 3.16 3.21:

Suggested change
Soft-deprecated since Python 3.13, scheduled for removal in Python 3.21.

Comment thread Doc/library/mimetypes.rst
.. deprecated:: 3.16
Passing a file path (or path-like object) instead of a URL.
Use :meth:`guess_file_type` instead.
Soft-deprecated since Python 3.13, scheduled for removal in Python 3.21.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Soft-deprecated since Python 3.13, scheduled for removal in Python 3.21.

Comment thread Doc/library/mimetypes.rst

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Use :meth:`guess_file_type` instead.
Use :func:`guess_file_type` instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deprecate passing file paths instead of URLs to mimetypes.guess_type()

4 participants