diff --git a/django/utils/encoding.py b/django/utils/encoding.py index 8f6f6024ca7..080b63d214c 100644 --- a/django/utils/encoding.py +++ b/django/utils/encoding.py @@ -253,7 +253,7 @@ def filepath_to_uri(path): return path # I know about `os.sep` and `os.altsep` but I want to leave # some flexibility for hardcoding separators. - return quote(path.replace("\\", "/"), safe="/~!*()'") + return quote(str(path).replace("\\", "/"), safe="/~!*()'") def get_system_encoding(): diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 4f174c5efe8..09b174c1ceb 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -280,7 +280,8 @@ The functions defined in this module share the following properties: .. function:: filepath_to_uri(path) Convert a file system path to a URI portion that is suitable for inclusion - in a URL. The path is assumed to be either UTF-8 bytes or string. + in a URL. The path is assumed to be either UTF-8 bytes, string, or a + :class:`~pathlib.Path`. This method will encode certain characters that would normally be recognized as special characters for URIs. Note that this method does not @@ -289,6 +290,10 @@ The functions defined in this module share the following properties: Returns an ASCII string containing the encoded result. + .. versionchanged:: 3.1 + + Support for :class:`pathlib.Path` ``path`` was added. + .. function:: escape_uri_path(path) Escapes the unsafe characters from the path portion of a Uniform Resource diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt index 0a08ce3cdff..d928abd2057 100644 --- a/docs/releases/3.1.txt +++ b/docs/releases/3.1.txt @@ -214,6 +214,12 @@ URLs * ... +Utilities +~~~~~~~~~ + +* :func:`~django.utils.encoding.filepath_to_uri` now supports + :class:`pathlib.Path`. + Validators ~~~~~~~~~~ diff --git a/tests/utils_tests/test_encoding.py b/tests/utils_tests/test_encoding.py index b878988e113..36f2d8665f3 100644 --- a/tests/utils_tests/test_encoding.py +++ b/tests/utils_tests/test_encoding.py @@ -1,6 +1,7 @@ import datetime import sys import unittest +from pathlib import Path from unittest import mock from urllib.parse import quote_plus @@ -106,6 +107,8 @@ class TestRFC3987IEncodingUtils(unittest.TestCase): def test_filepath_to_uri(self): self.assertIsNone(filepath_to_uri(None)) self.assertEqual(filepath_to_uri('upload\\чубака.mp4'), 'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4') + self.assertEqual(filepath_to_uri(Path('upload/test.png')), 'upload/test.png') + self.assertEqual(filepath_to_uri(Path('upload\\test.png')), 'upload/test.png') def test_iri_to_uri(self): cases = [