diff --git a/storages/utils.py b/storages/utils.py index 4a5d8f41c..45a66b9ea 100644 --- a/storages/utils.py +++ b/storages/utils.py @@ -1,4 +1,5 @@ import os +import pathlib import posixpath from django.conf import settings @@ -30,8 +31,14 @@ def setting(name, default=None): def clean_name(name): """ - Cleans the name so that Windows style paths work + Normalize the name. + + Includes cleaning up Windows style paths, ensuring an ending trailing slash, + and coercing from pathlib.Path. """ + if isinstance(name, pathlib.Path): + name = str(name) + # Normalize Windows style paths clean_name = posixpath.normpath(name).replace('\\', '/') @@ -39,7 +46,7 @@ def clean_name(name): # a workaround here. if name.endswith('/') and not clean_name.endswith('/'): # Add a trailing slash as it was stripped. - clean_name = clean_name + '/' + clean_name += '/' # Given an empty string, os.path.normpath() will return ., which we don't want if clean_name == '.': diff --git a/tests/test_utils.py b/tests/test_utils.py index e411d232c..252795037 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,4 +1,5 @@ import datetime +import pathlib from django.conf import settings from django.core.exceptions import SuspiciousFileOperation @@ -16,12 +17,15 @@ def test_get_setting(self): class CleanNameTests(TestCase): def test_clean_name(self): - """ - Test the base case of clean_name - """ + """Test the base case of clean_name.""" path = utils.clean_name("path/to/somewhere") self.assertEqual(path, "path/to/somewhere") + def test_clean_name_pathlib(self): + """Test for pathlib.Path handling.""" + path = pathlib.Path("path/to/anywhere") + self.assertEqual(utils.clean_name(path), "path/to/anywhere") + def test_clean_name_normalize(self): """ Test the normalization of clean_name @@ -30,16 +34,12 @@ def test_clean_name_normalize(self): self.assertEqual(path, "path/somewhere") def test_clean_name_trailing_slash(self): - """ - Test the clean_name when the path has a trailing slash - """ + """Test the clean_name when the path has a trailing slash.""" path = utils.clean_name("path/to/somewhere/") self.assertEqual(path, "path/to/somewhere/") def test_clean_name_windows(self): - """ - Test the clean_name when the path has a trailing slash - """ + """Test the clean_name when the path has a trailing slash.""" path = utils.clean_name("path\\to\\somewhere") self.assertEqual(path, "path/to/somewhere")