diff options
| author | django-bot <ops@djangoproject.com> | 2022-02-03 20:24:19 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-07 20:37:05 +0100 |
| commit | 9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch) | |
| tree | f0506b668a013d0063e5fba3dbf4863b466713ba /tests/file_storage | |
| parent | f68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff) | |
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'tests/file_storage')
| -rw-r--r-- | tests/file_storage/models.py | 36 | ||||
| -rw-r--r-- | tests/file_storage/test_generate_filename.py | 97 | ||||
| -rw-r--r-- | tests/file_storage/tests.py | 527 | ||||
| -rw-r--r-- | tests/file_storage/urls.py | 2 |
4 files changed, 364 insertions, 298 deletions
diff --git a/tests/file_storage/models.py b/tests/file_storage/models.py index 9097f465dd..7a60784349 100644 --- a/tests/file_storage/models.py +++ b/tests/file_storage/models.py @@ -16,7 +16,7 @@ from django.db import models class CustomValidNameStorage(FileSystemStorage): def get_valid_name(self, name): # mark the name to show that this was called - return name + '_valid' + return name + "_valid" temp_storage_location = tempfile.mkdtemp() @@ -35,28 +35,40 @@ class CallableStorage(FileSystemStorage): class Storage(models.Model): def custom_upload_to(self, filename): - return 'foo' + return "foo" def random_upload_to(self, filename): # This returns a different result each time, # to make sure it only gets called once. - return '%s/%s' % (random.randint(100, 999), filename) + return "%s/%s" % (random.randint(100, 999), filename) def pathlib_upload_to(self, filename): - return Path('bar') / filename + return Path("bar") / filename - normal = models.FileField(storage=temp_storage, upload_to='tests') + normal = models.FileField(storage=temp_storage, upload_to="tests") custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) - pathlib_callable = models.FileField(storage=temp_storage, upload_to=pathlib_upload_to) - pathlib_direct = models.FileField(storage=temp_storage, upload_to=Path('bar')) + pathlib_callable = models.FileField( + storage=temp_storage, upload_to=pathlib_upload_to + ) + pathlib_direct = models.FileField(storage=temp_storage, upload_to=Path("bar")) random = models.FileField(storage=temp_storage, upload_to=random_upload_to) custom_valid_name = models.FileField( storage=CustomValidNameStorage(location=temp_storage_location), upload_to=random_upload_to, ) - storage_callable = models.FileField(storage=callable_storage, upload_to='storage_callable') - storage_callable_class = models.FileField(storage=CallableStorage, upload_to='storage_callable_class') - default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt') + storage_callable = models.FileField( + storage=callable_storage, upload_to="storage_callable" + ) + storage_callable_class = models.FileField( + storage=CallableStorage, upload_to="storage_callable_class" + ) + default = models.FileField( + storage=temp_storage, upload_to="tests", default="tests/default.txt" + ) empty = models.FileField(storage=temp_storage) - limited_length = models.FileField(storage=temp_storage, upload_to='tests', max_length=20) - extended_length = models.FileField(storage=temp_storage, upload_to='tests', max_length=300) + limited_length = models.FileField( + storage=temp_storage, upload_to="tests", max_length=20 + ) + extended_length = models.FileField( + storage=temp_storage, upload_to="tests", max_length=300 + ) diff --git a/tests/file_storage/test_generate_filename.py b/tests/file_storage/test_generate_filename.py index 78fd064732..30d76c1a78 100644 --- a/tests/file_storage/test_generate_filename.py +++ b/tests/file_storage/test_generate_filename.py @@ -13,7 +13,8 @@ class AWSS3Storage(Storage): characters in file names but where there aren't actual folders but just keys. """ - prefix = 'mys3folder/' + + prefix = "mys3folder/" def _save(self, name, content): """ @@ -39,9 +40,9 @@ class AWSS3Storage(Storage): class GenerateFilenameStorageTests(SimpleTestCase): def test_storage_dangerous_paths(self): candidates = [ - ('/tmp/..', '..'), - ('/tmp/.', '.'), - ('', ''), + ("/tmp/..", ".."), + ("/tmp/.", "."), + ("", ""), ] s = FileSystemStorage() msg = "Could not derive file name from '%s'" @@ -54,10 +55,10 @@ class GenerateFilenameStorageTests(SimpleTestCase): def test_storage_dangerous_paths_dir_name(self): candidates = [ - ('tmp/../path', 'tmp/..'), - ('tmp\\..\\path', 'tmp/..'), - ('/tmp/../path', '/tmp/..'), - ('\\tmp\\..\\path', '/tmp/..'), + ("tmp/../path", "tmp/.."), + ("tmp\\..\\path", "tmp/.."), + ("/tmp/../path", "/tmp/.."), + ("\\tmp\\..\\path", "/tmp/.."), ] s = FileSystemStorage() for file_name, path in candidates: @@ -70,13 +71,13 @@ class GenerateFilenameStorageTests(SimpleTestCase): def test_filefield_dangerous_filename(self): candidates = [ - ('..', 'some/folder/..'), - ('.', 'some/folder/.'), - ('', 'some/folder/'), - ('???', '???'), - ('$.$.$', '$.$.$'), + ("..", "some/folder/.."), + (".", "some/folder/."), + ("", "some/folder/"), + ("???", "???"), + ("$.$.$", "$.$.$"), ] - f = FileField(upload_to='some/folder/') + f = FileField(upload_to="some/folder/") for file_name, msg_file_name in candidates: msg = f"Could not derive file name from '{msg_file_name}'" with self.subTest(file_name=file_name): @@ -84,16 +85,16 @@ class GenerateFilenameStorageTests(SimpleTestCase): f.generate_filename(None, file_name) def test_filefield_dangerous_filename_dot_segments(self): - f = FileField(upload_to='some/folder/') + f = FileField(upload_to="some/folder/") msg = "Detected path traversal attempt in 'some/folder/../path'" with self.assertRaisesMessage(SuspiciousFileOperation, msg): - f.generate_filename(None, '../path') + f.generate_filename(None, "../path") def test_filefield_generate_filename_absolute_path(self): - f = FileField(upload_to='some/folder/') + f = FileField(upload_to="some/folder/") candidates = [ - '/tmp/path', - '/tmp/../path', + "/tmp/path", + "/tmp/../path", ] for file_name in candidates: msg = f"Detected path traversal attempt in '{file_name}'" @@ -102,54 +103,54 @@ class GenerateFilenameStorageTests(SimpleTestCase): f.generate_filename(None, file_name) def test_filefield_generate_filename(self): - f = FileField(upload_to='some/folder/') + f = FileField(upload_to="some/folder/") self.assertEqual( - f.generate_filename(None, 'test with space.txt'), - os.path.normpath('some/folder/test_with_space.txt') + f.generate_filename(None, "test with space.txt"), + os.path.normpath("some/folder/test_with_space.txt"), ) def test_filefield_generate_filename_with_upload_to(self): def upload_to(instance, filename): - return 'some/folder/' + filename + return "some/folder/" + filename f = FileField(upload_to=upload_to) self.assertEqual( - f.generate_filename(None, 'test with space.txt'), - os.path.normpath('some/folder/test_with_space.txt') + f.generate_filename(None, "test with space.txt"), + os.path.normpath("some/folder/test_with_space.txt"), ) def test_filefield_generate_filename_upload_to_overrides_dangerous_filename(self): def upload_to(instance, filename): - return 'test.txt' + return "test.txt" f = FileField(upload_to=upload_to) candidates = [ - '/tmp/.', - '/tmp/..', - '/tmp/../path', - '/tmp/path', - 'some/folder/', - 'some/folder/.', - 'some/folder/..', - 'some/folder/???', - 'some/folder/$.$.$', - 'some/../test.txt', - '', + "/tmp/.", + "/tmp/..", + "/tmp/../path", + "/tmp/path", + "some/folder/", + "some/folder/.", + "some/folder/..", + "some/folder/???", + "some/folder/$.$.$", + "some/../test.txt", + "", ] for file_name in candidates: with self.subTest(file_name=file_name): - self.assertEqual(f.generate_filename(None, file_name), 'test.txt') + self.assertEqual(f.generate_filename(None, file_name), "test.txt") def test_filefield_generate_filename_upload_to_absolute_path(self): def upload_to(instance, filename): - return '/tmp/' + filename + return "/tmp/" + filename f = FileField(upload_to=upload_to) candidates = [ - 'path', - '../path', - '???', - '$.$.$', + "path", + "../path", + "???", + "$.$.$", ] for file_name in candidates: msg = f"Detected path traversal attempt in '/tmp/{file_name}'" @@ -159,10 +160,10 @@ class GenerateFilenameStorageTests(SimpleTestCase): def test_filefield_generate_filename_upload_to_dangerous_filename(self): def upload_to(instance, filename): - return '/tmp/' + filename + return "/tmp/" + filename f = FileField(upload_to=upload_to) - candidates = ['..', '.', ''] + candidates = ["..", ".", ""] for file_name in candidates: msg = f"Could not derive file name from '/tmp/{file_name}'" with self.subTest(file_name=file_name): @@ -176,11 +177,11 @@ class GenerateFilenameStorageTests(SimpleTestCase): calls that break the key. """ storage = AWSS3Storage() - folder = 'not/a/folder/' + folder = "not/a/folder/" f = FileField(upload_to=folder, storage=storage) - key = 'my-file-key\\with odd characters' - data = ContentFile('test') + key = "my-file-key\\with odd characters" + data = ContentFile("test") expected_key = AWSS3Storage.prefix + folder + key # Simulate call to f.save() diff --git a/tests/file_storage/tests.py b/tests/file_storage/tests.py index 66edbb204f..6d6949ef01 100644 --- a/tests/file_storage/tests.py +++ b/tests/file_storage/tests.py @@ -13,73 +13,73 @@ from urllib.request import urlopen from django.core.cache import cache from django.core.exceptions import SuspiciousFileOperation from django.core.files.base import ContentFile, File -from django.core.files.storage import ( - FileSystemStorage, Storage as BaseStorage, default_storage, - get_storage_class, -) +from django.core.files.storage import FileSystemStorage +from django.core.files.storage import Storage as BaseStorage +from django.core.files.storage import default_storage, get_storage_class from django.core.files.uploadedfile import ( - InMemoryUploadedFile, SimpleUploadedFile, TemporaryUploadedFile, + InMemoryUploadedFile, + SimpleUploadedFile, + TemporaryUploadedFile, ) from django.db.models import FileField from django.db.models.fields.files import FileDescriptor -from django.test import ( - LiveServerTestCase, SimpleTestCase, TestCase, override_settings, -) +from django.test import LiveServerTestCase, SimpleTestCase, TestCase, override_settings from django.test.utils import requires_tz_support from django.urls import NoReverseMatch, reverse_lazy from django.utils import timezone from django.utils._os import symlinks_supported -from .models import ( - Storage, callable_storage, temp_storage, temp_storage_location, -) +from .models import Storage, callable_storage, temp_storage, temp_storage_location -FILE_SUFFIX_REGEX = '[A-Za-z0-9]{7}' +FILE_SUFFIX_REGEX = "[A-Za-z0-9]{7}" class GetStorageClassTests(SimpleTestCase): - def test_get_filesystem_storage(self): """ get_storage_class returns the class for a storage backend name/path. """ self.assertEqual( - get_storage_class('django.core.files.storage.FileSystemStorage'), - FileSystemStorage) + get_storage_class("django.core.files.storage.FileSystemStorage"), + FileSystemStorage, + ) def test_get_invalid_storage_module(self): """ get_storage_class raises an error if the requested import don't exist. """ with self.assertRaisesMessage(ImportError, "No module named 'storage'"): - get_storage_class('storage.NonexistentStorage') + get_storage_class("storage.NonexistentStorage") def test_get_nonexistent_storage_class(self): """ get_storage_class raises an error if the requested class don't exist. """ with self.assertRaises(ImportError): - get_storage_class('django.core.files.storage.NonexistentStorage') + get_storage_class("django.core.files.storage.NonexistentStorage") def test_get_nonexistent_storage_module(self): """ get_storage_class raises an error if the requested module don't exist. """ - with self.assertRaisesMessage(ImportError, "No module named 'django.core.files.nonexistent_storage'"): - get_storage_class('django.core.files.nonexistent_storage.NonexistentStorage') + with self.assertRaisesMessage( + ImportError, "No module named 'django.core.files.nonexistent_storage'" + ): + get_storage_class( + "django.core.files.nonexistent_storage.NonexistentStorage" + ) class FileSystemStorageTests(unittest.TestCase): - def test_deconstruction(self): path, args, kwargs = temp_storage.deconstruct() self.assertEqual(path, "django.core.files.storage.FileSystemStorage") self.assertEqual(args, ()) - self.assertEqual(kwargs, {'location': temp_storage_location}) + self.assertEqual(kwargs, {"location": temp_storage_location}) kwargs_orig = { - 'location': temp_storage_location, - 'base_url': 'http://myfiles.example.com/' + "location": temp_storage_location, + "base_url": "http://myfiles.example.com/", } storage = FileSystemStorage(**kwargs_orig) path, args, kwargs = storage.deconstruct() @@ -89,7 +89,7 @@ class FileSystemStorageTests(unittest.TestCase): """ FileSystemStorage.__init__() shouldn't evaluate base_url. """ - storage = FileSystemStorage(base_url=reverse_lazy('app:url')) + storage = FileSystemStorage(base_url=reverse_lazy("app:url")) with self.assertRaises(NoReverseMatch): storage.url(storage.base_url) @@ -99,10 +99,12 @@ class FileStorageTests(SimpleTestCase): def setUp(self): self.temp_dir = tempfile.mkdtemp() - self.storage = self.storage_class(location=self.temp_dir, base_url='/test_media_url/') + self.storage = self.storage_class( + location=self.temp_dir, base_url="/test_media_url/" + ) # Set up a second temporary directory which is ensured to have a mixed # case name. - self.temp_dir2 = tempfile.mkdtemp(suffix='aBc') + self.temp_dir2 = tempfile.mkdtemp(suffix="aBc") def tearDown(self): shutil.rmtree(self.temp_dir) @@ -112,26 +114,26 @@ class FileStorageTests(SimpleTestCase): """ Makes sure an exception is raised if the location is empty """ - storage = self.storage_class(location='') - self.assertEqual(storage.base_location, '') + storage = self.storage_class(location="") + self.assertEqual(storage.base_location, "") self.assertEqual(storage.location, os.getcwd()) def test_file_access_options(self): """ Standard file access options are available, and work as expected. """ - self.assertFalse(self.storage.exists('storage_test')) - f = self.storage.open('storage_test', 'w') - f.write('storage contents') + self.assertFalse(self.storage.exists("storage_test")) + f = self.storage.open("storage_test", "w") + f.write("storage contents") f.close() - self.assertTrue(self.storage.exists('storage_test')) + self.assertTrue(self.storage.exists("storage_test")) - f = self.storage.open('storage_test', 'r') - self.assertEqual(f.read(), 'storage contents') + f = self.storage.open("storage_test", "r") + self.assertEqual(f.read(), "storage contents") f.close() - self.storage.delete('storage_test') - self.assertFalse(self.storage.exists('storage_test')) + self.storage.delete("storage_test") + self.assertFalse(self.storage.exists("storage_test")) def _test_file_time_getter(self, getter): # Check for correct behavior under both USE_TZ=True and USE_TZ=False. @@ -140,7 +142,7 @@ class FileStorageTests(SimpleTestCase): self._test_file_time_getter_tz_handling_on(getter) self._test_file_time_getter_tz_handling_off(getter) - @override_settings(USE_TZ=True, TIME_ZONE='Africa/Algiers') + @override_settings(USE_TZ=True, TIME_ZONE="Africa/Algiers") def _test_file_time_getter_tz_handling_on(self, getter): # Django's TZ (and hence the system TZ) is set to Africa/Algiers which # is UTC+1 and has no DST change. We can set the Django TZ to something @@ -152,10 +154,10 @@ class FileStorageTests(SimpleTestCase): # At this point the system TZ is +1 and the Django TZ # is -5. The following will be aware in UTC. now = timezone.now() - self.assertFalse(self.storage.exists('test.file.tz.on')) + self.assertFalse(self.storage.exists("test.file.tz.on")) - f = ContentFile('custom contents') - f_name = self.storage.save('test.file.tz.on', f) + f = ContentFile("custom contents") + f_name = self.storage.save("test.file.tz.on", f) self.addCleanup(self.storage.delete, f_name) dt = getter(f_name) # dt should be aware, in UTC @@ -173,7 +175,7 @@ class FileStorageTests(SimpleTestCase): # dt and now should be the same effective time. self.assertLess(abs(dt - now), timedelta(seconds=2)) - @override_settings(USE_TZ=False, TIME_ZONE='Africa/Algiers') + @override_settings(USE_TZ=False, TIME_ZONE="Africa/Algiers") def _test_file_time_getter_tz_handling_off(self, getter): # Django's TZ (and hence the system TZ) is set to Africa/Algiers which # is UTC+1 and has no DST change. We can set the Django TZ to something @@ -184,10 +186,10 @@ class FileStorageTests(SimpleTestCase): with timezone.override(timezone.get_fixed_timezone(-300)): # At this point the system TZ is +1 and the Django TZ # is -5. - self.assertFalse(self.storage.exists('test.file.tz.off')) + self.assertFalse(self.storage.exists("test.file.tz.off")) - f = ContentFile('custom contents') - f_name = self.storage.save('test.file.tz.off', f) + f = ContentFile("custom contents") + f_name = self.storage.save("test.file.tz.off", f) self.addCleanup(self.storage.delete, f_name) dt = getter(f_name) # dt should be naive, in system (+1) TZ @@ -214,15 +216,20 @@ class FileStorageTests(SimpleTestCase): File storage returns a Datetime object for the last accessed time of a file. """ - self.assertFalse(self.storage.exists('test.file')) + self.assertFalse(self.storage.exists("test.file")) - f = ContentFile('custom contents') - f_name = self.storage.save('test.file', f) + f = ContentFile("custom contents") + f_name = self.storage.save("test.file", f) self.addCleanup(self.storage.delete, f_name) atime = self.storage.get_accessed_time(f_name) - self.assertEqual(atime, datetime.fromtimestamp(os.path.getatime(self.storage.path(f_name)))) - self.assertLess(timezone.now() - self.storage.get_accessed_time(f_name), timedelta(seconds=2)) + self.assertEqual( + atime, datetime.fromtimestamp(os.path.getatime(self.storage.path(f_name))) + ) + self.assertLess( + timezone.now() - self.storage.get_accessed_time(f_name), + timedelta(seconds=2), + ) @requires_tz_support def test_file_get_accessed_time_timezone(self): @@ -232,15 +239,19 @@ class FileStorageTests(SimpleTestCase): """ File storage returns a datetime for the creation time of a file. """ - self.assertFalse(self.storage.exists('test.file')) + self.assertFalse(self.storage.exists("test.file")) - f = ContentFile('custom contents') - f_name = self.storage.save('test.file', f) + f = ContentFile("custom contents") + f_name = self.storage.save("test.file", f) self.addCleanup(self.storage.delete, f_name) ctime = self.storage.get_created_time(f_name) - self.assertEqual(ctime, datetime.fromtimestamp(os.path.getctime(self.storage.path(f_name)))) - self.assertLess(timezone.now() - self.storage.get_created_time(f_name), timedelta(seconds=2)) + self.assertEqual( + ctime, datetime.fromtimestamp(os.path.getctime(self.storage.path(f_name))) + ) + self.assertLess( + timezone.now() - self.storage.get_created_time(f_name), timedelta(seconds=2) + ) @requires_tz_support def test_file_get_created_time_timezone(self): @@ -250,15 +261,20 @@ class FileStorageTests(SimpleTestCase): """ File storage returns a datetime for the last modified time of a file. """ - self.assertFalse(self.storage.exists('test.file')) + self.assertFalse(self.storage.exists("test.file")) - f = ContentFile('custom contents') - f_name = self.storage.save('test.file', f) + f = ContentFile("custom contents") + f_name = self.storage.save("test.file", f) self.addCleanup(self.storage.delete, f_name) mtime = self.storage.get_modified_time(f_name) - self.assertEqual(mtime, datetime.fromtimestamp(os.path.getmtime(self.storage.path(f_name)))) - self.assertLess(timezone.now() - self.storage.get_modified_time(f_name), timedelta(seconds=2)) + self.assertEqual( + mtime, datetime.fromtimestamp(os.path.getmtime(self.storage.path(f_name))) + ) + self.assertLess( + timezone.now() - self.storage.get_modified_time(f_name), + timedelta(seconds=2), + ) @requires_tz_support def test_file_get_modified_time_timezone(self): @@ -269,10 +285,10 @@ class FileStorageTests(SimpleTestCase): File storage extracts the filename from the content object if no name is given explicitly. """ - self.assertFalse(self.storage.exists('test.file')) + self.assertFalse(self.storage.exists("test.file")) - f = ContentFile('custom contents') - f.name = 'test.file' + f = ContentFile("custom contents") + f.name = "test.file" storage_f_name = self.storage.save(None, f) @@ -286,47 +302,50 @@ class FileStorageTests(SimpleTestCase): """ Saving a pathname should create intermediate directories as necessary. """ - self.assertFalse(self.storage.exists('path/to')) - self.storage.save('path/to/test.file', ContentFile('file saved with path')) + self.assertFalse(self.storage.exists("path/to")) + self.storage.save("path/to/test.file", ContentFile("file saved with path")) - self.assertTrue(self.storage.exists('path/to')) - with self.storage.open('path/to/test.file') as f: - self.assertEqual(f.read(), b'file saved with path') + self.assertTrue(self.storage.exists("path/to")) + with self.storage.open("path/to/test.file") as f: + self.assertEqual(f.read(), b"file saved with path") - self.assertTrue(os.path.exists( - os.path.join(self.temp_dir, 'path', 'to', 'test.file'))) + self.assertTrue( + os.path.exists(os.path.join(self.temp_dir, "path", "to", "test.file")) + ) - self.storage.delete('path/to/test.file') + self.storage.delete("path/to/test.file") def test_file_save_abs_path(self): - test_name = 'path/to/test.file' - f = ContentFile('file saved with path') + test_name = "path/to/test.file" + f = ContentFile("file saved with path") f_name = self.storage.save(os.path.join(self.temp_dir, test_name), f) self.assertEqual(f_name, test_name) - @unittest.skipUnless(symlinks_supported(), 'Must be able to symlink to run this test.') + @unittest.skipUnless( + symlinks_supported(), "Must be able to symlink to run this test." + ) def test_file_save_broken_symlink(self): """A new path is created on save when a broken symlink is supplied.""" - nonexistent_file_path = os.path.join(self.temp_dir, 'nonexistent.txt') - broken_symlink_path = os.path.join(self.temp_dir, 'symlink.txt') + nonexistent_file_path = os.path.join(self.temp_dir, "nonexistent.txt") + broken_symlink_path = os.path.join(self.temp_dir, "symlink.txt") os.symlink(nonexistent_file_path, broken_symlink_path) - f = ContentFile('some content') + f = ContentFile("some content") f_name = self.storage.save(broken_symlink_path, f) self.assertIs(os.path.exists(os.path.join(self.temp_dir, f_name)), True) def test_save_doesnt_close(self): - with TemporaryUploadedFile('test', 'text/plain', 1, 'utf8') as file: - file.write(b'1') + with TemporaryUploadedFile("test", "text/plain", 1, "utf8") as file: + file.write(b"1") file.seek(0) self.assertFalse(file.closed) - self.storage.save('path/to/test.file', file) + self.storage.save("path/to/test.file", file) self.assertFalse(file.closed) self.assertFalse(file.file.closed) - file = InMemoryUploadedFile(StringIO('1'), '', 'test', 'text/plain', 1, 'utf8') + file = InMemoryUploadedFile(StringIO("1"), "", "test", "text/plain", 1, "utf8") with file: self.assertFalse(file.closed) - self.storage.save('path/to/test.file', file) + self.storage.save("path/to/test.file", file) self.assertFalse(file.closed) self.assertFalse(file.file.closed) @@ -334,10 +353,10 @@ class FileStorageTests(SimpleTestCase): """ File storage returns the full path of a file """ - self.assertFalse(self.storage.exists('test.file')) + self.assertFalse(self.storage.exists("test.file")) - f = ContentFile('custom contents') - f_name = self.storage.save('test.file', f) + f = ContentFile("custom contents") + f_name = self.storage.save("test.file", f) self.assertEqual(self.storage.path(f_name), os.path.join(self.temp_dir, f_name)) @@ -347,18 +366,22 @@ class FileStorageTests(SimpleTestCase): """ File storage returns a url to access a given file from the web. """ - self.assertEqual(self.storage.url('test.file'), self.storage.base_url + 'test.file') + self.assertEqual( + self.storage.url("test.file"), self.storage.base_url + "test.file" + ) # should encode special chars except ~!*()' # like encodeURIComponent() JavaScript function do self.assertEqual( self.storage.url(r"~!*()'@#$%^&*abc`+ =.file"), - "/test_media_url/~!*()'%40%23%24%25%5E%26*abc%60%2B%20%3D.file" + "/test_media_url/~!*()'%40%23%24%25%5E%26*abc%60%2B%20%3D.file", ) self.assertEqual(self.storage.url("ab\0c"), "/test_media_url/ab%00c") # should translate os path separator(s) to the url path separator - self.assertEqual(self.storage.url("""a/b\\c.file"""), "/test_media_url/a/b/c.file") + self.assertEqual( + self.storage.url("""a/b\\c.file"""), "/test_media_url/a/b/c.file" + ) # #25905: remove leading slashes from file names to prevent unsafe url output self.assertEqual(self.storage.url("/evil.com"), "/test_media_url/evil.com") @@ -374,35 +397,36 @@ class FileStorageTests(SimpleTestCase): """ self.storage.base_url = None with self.assertRaises(ValueError): - self.storage.url('test.file') + self.storage.url("test.file") # #22717: missing ending slash in base_url should be auto-corrected - storage = self.storage_class(location=self.temp_dir, base_url='/no_ending_slash') + storage = self.storage_class( + location=self.temp_dir, base_url="/no_ending_slash" + ) self.assertEqual( - storage.url('test.file'), - '%s%s' % (storage.base_url, 'test.file') + storage.url("test.file"), "%s%s" % (storage.base_url, "test.file") ) def test_listdir(self): """ File storage returns a tuple containing directories and files. """ - self.assertFalse(self.storage.exists('storage_test_1')) - self.assertFalse(self.storage.exists('storage_test_2')) - self.assertFalse(self.storage.exists('storage_dir_1')) + self.assertFalse(self.storage.exists("storage_test_1")) + self.assertFalse(self.storage.exists("storage_test_2")) + self.assertFalse(self.storage.exists("storage_dir_1")) - self.storage.save('storage_test_1', ContentFile('custom content')) - self.storage.save('storage_test_2', ContentFile('custom content')) - os.mkdir(os.path.join(self.temp_dir, 'storage_dir_1')) + self.storage.save("storage_test_1", ContentFile("custom content")) + self.storage.save("storage_test_2", ContentFile("custom content")) + os.mkdir(os.path.join(self.temp_dir, "storage_dir_1")) - self.addCleanup(self.storage.delete, 'storage_test_1') - self.addCleanup(self.storage.delete, 'storage_test_2') + self.addCleanup(self.storage.delete, "storage_test_1") + self.addCleanup(self.storage.delete, "storage_test_2") - for directory in ('', Path('')): + for directory in ("", Path("")): with self.subTest(directory=directory): dirs, files = self.storage.listdir(directory) - self.assertEqual(set(dirs), {'storage_dir_1'}) - self.assertEqual(set(files), {'storage_test_1', 'storage_test_2'}) + self.assertEqual(set(dirs), {"storage_dir_1"}) + self.assertEqual(set(files), {"storage_test_1", "storage_test_2"}) def test_file_storage_prevents_directory_traversal(self): """ @@ -410,9 +434,9 @@ class FileStorageTests(SimpleTestCase): they're below the storage location). """ with self.assertRaises(SuspiciousFileOperation): - self.storage.exists('..') + self.storage.exists("..") with self.assertRaises(SuspiciousFileOperation): - self.storage.exists('/etc/passwd') + self.storage.exists("/etc/passwd") def test_file_storage_preserves_filename_case(self): """The storage backend should preserve case of filenames.""" @@ -420,11 +444,14 @@ class FileStorageTests(SimpleTestCase): # directory. other_temp_storage = self.storage_class(location=self.temp_dir2) # Ask that storage backend to store a file with a mixed case filename. - mixed_case = 'CaSe_SeNsItIvE' - file = other_temp_storage.open(mixed_case, 'w') - file.write('storage contents') + mixed_case = "CaSe_SeNsItIvE" + file = other_temp_storage.open(mixed_case, "w") + file.write("storage contents") file.close() - self.assertEqual(os.path.join(self.temp_dir2, mixed_case), other_temp_storage.path(mixed_case)) + self.assertEqual( + os.path.join(self.temp_dir2, mixed_case), + other_temp_storage.path(mixed_case), + ) other_temp_storage.delete(mixed_case) def test_makedirs_race_handling(self): @@ -436,31 +463,31 @@ class FileStorageTests(SimpleTestCase): # Monkey-patch os.makedirs, to simulate a normal call, a raced call, # and an error. def fake_makedirs(path, mode=0o777, exist_ok=False): - if path == os.path.join(self.temp_dir, 'normal'): + if path == os.path.join(self.temp_dir, "normal"): real_makedirs(path, mode, exist_ok) - elif path == os.path.join(self.temp_dir, 'raced'): + elif path == os.path.join(self.temp_dir, "raced"): real_makedirs(path, mode, exist_ok) if not exist_ok: raise FileExistsError() - elif path == os.path.join(self.temp_dir, 'error'): + elif path == os.path.join(self.temp_dir, "error"): raise PermissionError() else: - self.fail('unexpected argument %r' % path) + self.fail("unexpected argument %r" % path) try: os.makedirs = fake_makedirs - self.storage.save('normal/test.file', ContentFile('saved normally')) - with self.storage.open('normal/test.file') as f: - self.assertEqual(f.read(), b'saved normally') + self.storage.save("normal/test.file", ContentFile("saved normally")) + with self.storage.open("normal/test.file") as f: + self.assertEqual(f.read(), b"saved normally") - self.storage.save('raced/test.file', ContentFile('saved with race')) - with self.storage.open('raced/test.file') as f: - self.assertEqual(f.read(), b'saved with race') + self.storage.save("raced/test.file", ContentFile("saved with race")) + with self.storage.open("raced/test.file") as f: + self.assertEqual(f.read(), b"saved with race") # Exceptions aside from FileExistsError are raised. with self.assertRaises(PermissionError): - self.storage.save('error/test.file', ContentFile('not saved')) + self.storage.save("error/test.file", ContentFile("not saved")) finally: os.makedirs = real_makedirs @@ -473,31 +500,31 @@ class FileStorageTests(SimpleTestCase): # Monkey-patch os.remove, to simulate a normal call, a raced call, # and an error. def fake_remove(path): - if path == os.path.join(self.temp_dir, 'normal.file'): + if path == os.path.join(self.temp_dir, "normal.file"): real_remove(path) - elif path == os.path.join(self.temp_dir, 'raced.file'): + elif path == os.path.join(self.temp_dir, "raced.file"): real_remove(path) raise FileNotFoundError() - elif path == os.path.join(self.temp_dir, 'error.file'): + elif path == os.path.join(self.temp_dir, "error.file"): raise PermissionError() else: - self.fail('unexpected argument %r' % path) + self.fail("unexpected argument %r" % path) try: os.remove = fake_remove - self.storage.save('normal.file', ContentFile('delete normally')) - self.storage.delete('normal.file') - self.assertFalse(self.storage.exists('normal.file')) + self.storage.save("normal.file", ContentFile("delete normally")) + self.storage.delete("normal.file") + self.assertFalse(self.storage.exists("normal.file")) - self.storage.save('raced.file', ContentFile('delete with race')) - self.storage.delete('raced.file') - self.assertFalse(self.storage.exists('normal.file')) + self.storage.save("raced.file", ContentFile("delete with race")) + self.storage.delete("raced.file") + self.assertFalse(self.storage.exists("normal.file")) # Exceptions aside from FileNotFoundError are raised. - self.storage.save('error.file', ContentFile('delete with error')) + self.storage.save("error.file", ContentFile("delete with error")) with self.assertRaises(PermissionError): - self.storage.delete('error.file') + self.storage.delete("error.file") finally: os.remove = real_remove @@ -505,24 +532,25 @@ class FileStorageTests(SimpleTestCase): """ Test behavior when file.chunks() is raising an error """ - f1 = ContentFile('chunks fails') + f1 = ContentFile("chunks fails") def failing_chunks(): raise OSError + f1.chunks = failing_chunks with self.assertRaises(OSError): - self.storage.save('error.file', f1) + self.storage.save("error.file", f1) def test_delete_no_name(self): """ Calling delete with an empty name should not try to remove the base storage directory, but fail loudly (#20660). """ - msg = 'The name must be given to delete().' + msg = "The name must be given to delete()." with self.assertRaisesMessage(ValueError, msg): self.storage.delete(None) with self.assertRaisesMessage(ValueError, msg): - self.storage.delete('') + self.storage.delete("") def test_delete_deletes_directories(self): tmp_dir = tempfile.mkdtemp(dir=self.storage.location) @@ -530,8 +558,8 @@ class FileStorageTests(SimpleTestCase): self.assertFalse(os.path.exists(tmp_dir)) @override_settings( - MEDIA_ROOT='media_root', - MEDIA_URL='media_url/', + MEDIA_ROOT="media_root", + MEDIA_URL="media_url/", FILE_UPLOAD_PERMISSIONS=0o777, FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777, ) @@ -541,43 +569,47 @@ class FileStorageTests(SimpleTestCase): referenced settings change while specified values should be unchanged. """ storage = self.storage_class( - location='explicit_location', - base_url='explicit_base_url/', + location="explicit_location", + base_url="explicit_base_url/", file_permissions_mode=0o666, directory_permissions_mode=0o666, ) defaults_storage = self.storage_class() settings = { - 'MEDIA_ROOT': 'overridden_media_root', - 'MEDIA_URL': '/overridden_media_url/', - 'FILE_UPLOAD_PERMISSIONS': 0o333, - 'FILE_UPLOAD_DIRECTORY_PERMISSIONS': 0o333, + "MEDIA_ROOT": "overridden_media_root", + "MEDIA_URL": "/overridden_media_url/", + "FILE_UPLOAD_PERMISSIONS": 0o333, + "FILE_UPLOAD_DIRECTORY_PERMISSIONS": 0o333, } with self.settings(**settings): - self.assertEqual(storage.base_location, 'explicit_location') - self.assertIn('explicit_location', storage.location) - self.assertEqual(storage.base_url, 'explicit_base_url/') + self.assertEqual(storage.base_location, "explicit_location") + self.assertIn("explicit_location", storage.location) + self.assertEqual(storage.base_url, "explicit_base_url/") self.assertEqual(storage.file_permissions_mode, 0o666) self.assertEqual(storage.directory_permissions_mode, 0o666) - self.assertEqual(defaults_storage.base_location, settings['MEDIA_ROOT']) - self.assertIn(settings['MEDIA_ROOT'], defaults_storage.location) - self.assertEqual(defaults_storage.base_url, settings['MEDIA_URL']) - self.assertEqual(defaults_storage.file_permissions_mode, settings['FILE_UPLOAD_PERMISSIONS']) + self.assertEqual(defaults_storage.base_location, settings["MEDIA_ROOT"]) + self.assertIn(settings["MEDIA_ROOT"], defaults_storage.location) + self.assertEqual(defaults_storage.base_url, settings["MEDIA_URL"]) self.assertEqual( - defaults_storage.directory_permissions_mode, settings['FILE_UPLOAD_DIRECTORY_PERMISSIONS'] + defaults_storage.file_permissions_mode, + settings["FILE_UPLOAD_PERMISSIONS"], + ) + self.assertEqual( + defaults_storage.directory_permissions_mode, + settings["FILE_UPLOAD_DIRECTORY_PERMISSIONS"], ) def test_file_methods_pathlib_path(self): - p = Path('test.file') + p = Path("test.file") self.assertFalse(self.storage.exists(p)) - f = ContentFile('custom contents') + f = ContentFile("custom contents") f_name = self.storage.save(p, f) # Storage basic methods. self.assertEqual(self.storage.path(p), os.path.join(self.temp_dir, p)) self.assertEqual(self.storage.size(p), 15) self.assertEqual(self.storage.url(p), self.storage.base_url + f_name) with self.storage.open(p) as f: - self.assertEqual(f.read(), b'custom contents') + self.assertEqual(f.read(), b"custom contents") self.addCleanup(self.storage.delete, p) @@ -589,7 +621,7 @@ class CustomStorage(FileSystemStorage): basename, *ext = os.path.splitext(name) number = 2 while self.exists(name): - name = ''.join([basename, '.', str(number)] + ext) + name = "".join([basename, ".", str(number)] + ext) number += 1 return name @@ -599,10 +631,10 @@ class CustomStorageTests(FileStorageTests): storage_class = CustomStorage def test_custom_get_available_name(self): - first = self.storage.save('custom_storage', ContentFile('custom contents')) - self.assertEqual(first, 'custom_storage') - second = self.storage.save('custom_storage', ContentFile('more contents')) - self.assertEqual(second, 'custom_storage.2') + first = self.storage.save("custom_storage", ContentFile("custom contents")) + self.assertEqual(first, "custom_storage") + second = self.storage.save("custom_storage", ContentFile("more contents")) + self.assertEqual(second, "custom_storage.2") self.storage.delete(first) self.storage.delete(second) @@ -612,6 +644,7 @@ class OverwritingStorage(FileSystemStorage): Overwrite existing files instead of appending a suffix to generate an unused name. """ + # Mask out O_EXCL so os.open() doesn't raise OSError if the file exists. OS_OPEN_FLAGS = FileSystemStorage.OS_OPEN_FLAGS & ~os.O_EXCL @@ -625,10 +658,10 @@ class OverwritingStorageTests(FileStorageTests): def test_save_overwrite_behavior(self): """Saving to same file name twice overwrites the first file.""" - name = 'test.file' + name = "test.file" self.assertFalse(self.storage.exists(name)) - content_1 = b'content one' - content_2 = b'second content' + content_1 = b"content one" + content_2 = b"second content" f_1 = ContentFile(content_1) f_2 = ContentFile(content_2) stored_name_1 = self.storage.save(name, f_1) @@ -652,7 +685,7 @@ class DiscardingFalseContentStorage(FileSystemStorage): def _save(self, name, content): if content: return super()._save(name, content) - return '' + return "" class DiscardingFalseContentStorageTests(FileStorageTests): @@ -663,12 +696,12 @@ class DiscardingFalseContentStorageTests(FileStorageTests): When Storage.save() wraps a file-like object in File, it should include the name argument so that bool(file) evaluates to True (#26495). """ - output = StringIO('content') - self.storage.save('tests/stringio', output) - self.assertTrue(self.storage.exists('tests/stringio')) + output = StringIO("content") + self.storage.save("tests/stringio", output) + self.assertTrue(self.storage.exists("tests/stringio")) - with self.storage.open('tests/stringio') as f: - self.assertEqual(f.read(), b'content') + with self.storage.open("tests/stringio") as f: + self.assertEqual(f.read(), b"content") class FileFieldStorageTests(TestCase): @@ -683,7 +716,7 @@ class FileFieldStorageTests(TestCase): while not os.path.exists(dir_to_test): dir_to_test = os.path.dirname(dir_to_test) try: - return os.pathconf(dir_to_test, 'PC_NAME_MAX') + return os.pathconf(dir_to_test, "PC_NAME_MAX") except Exception: return 255 # Should be safe on most backends @@ -726,31 +759,40 @@ class FileFieldStorageTests(TestCase): obj2.delete() obj2.normal.save("django_test.txt", ContentFile("more content")) self.assertNotEqual(obj2_name, obj2.normal.name) - self.assertRegex(obj2.normal.name, "tests/django_test_%s.txt" % FILE_SUFFIX_REGEX) + self.assertRegex( + obj2.normal.name, "tests/django_test_%s.txt" % FILE_SUFFIX_REGEX + ) obj2.normal.close() def test_filefield_read(self): # Files can be read in a little at a time, if necessary. obj = Storage.objects.create( - normal=SimpleUploadedFile("assignment.txt", b"content")) + normal=SimpleUploadedFile("assignment.txt", b"content") + ) obj.normal.open() self.assertEqual(obj.normal.read(3), b"con") self.assertEqual(obj.normal.read(), b"tent") - self.assertEqual(list(obj.normal.chunks(chunk_size=2)), [b"co", b"nt", b"en", b"t"]) + self.assertEqual( + list(obj.normal.chunks(chunk_size=2)), [b"co", b"nt", b"en", b"t"] + ) obj.normal.close() def test_filefield_write(self): # Files can be written to. - obj = Storage.objects.create(normal=SimpleUploadedFile('rewritten.txt', b'content')) + obj = Storage.objects.create( + normal=SimpleUploadedFile("rewritten.txt", b"content") + ) with obj.normal as normal: - normal.open('wb') - normal.write(b'updated') + normal.open("wb") + normal.write(b"updated") obj.refresh_from_db() - self.assertEqual(obj.normal.read(), b'updated') + self.assertEqual(obj.normal.read(), b"updated") obj.normal.close() def test_filefield_reopen(self): - obj = Storage.objects.create(normal=SimpleUploadedFile('reopen.txt', b'content')) + obj = Storage.objects.create( + normal=SimpleUploadedFile("reopen.txt", b"content") + ) with obj.normal as normal: normal.open() obj.normal.open() @@ -765,7 +807,9 @@ class FileFieldStorageTests(TestCase): try: names = [o.normal.name for o in objs] self.assertEqual(names[0], "tests/multiple_files.txt") - self.assertRegex(names[1], "tests/multiple_files_%s.txt" % FILE_SUFFIX_REGEX) + self.assertRegex( + names[1], "tests/multiple_files_%s.txt" % FILE_SUFFIX_REGEX + ) finally: for o in objs: o.delete() @@ -777,42 +821,46 @@ class FileFieldStorageTests(TestCase): # dirname + extension and there are not enough characters in the # filename to truncate, an exception should be raised. objs = [Storage() for i in range(2)] - filename = 'filename.ext' + filename = "filename.ext" for o in objs: - o.limited_length.save(filename, ContentFile('Same Content')) + o.limited_length.save(filename, ContentFile("Same Content")) try: # Testing truncation. names = [o.limited_length.name for o in objs] - self.assertEqual(names[0], 'tests/%s' % filename) - self.assertRegex(names[1], 'tests/fi_%s.ext' % FILE_SUFFIX_REGEX) + self.assertEqual(names[0], "tests/%s" % filename) + self.assertRegex(names[1], "tests/fi_%s.ext" % FILE_SUFFIX_REGEX) # Testing exception is raised when filename is too short to truncate. - filename = 'short.longext' - objs[0].limited_length.save(filename, ContentFile('Same Content')) - with self.assertRaisesMessage(SuspiciousFileOperation, 'Storage can not find an available filename'): - objs[1].limited_length.save(*(filename, ContentFile('Same Content'))) + filename = "short.longext" + objs[0].limited_length.save(filename, ContentFile("Same Content")) + with self.assertRaisesMessage( + SuspiciousFileOperation, "Storage can not find an available filename" + ): + objs[1].limited_length.save(*(filename, ContentFile("Same Content"))) finally: for o in objs: o.delete() @unittest.skipIf( - sys.platform == 'win32', + sys.platform == "win32", "Windows supports at most 260 characters in a path.", ) def test_extended_length_storage(self): # Testing FileField with max_length > 255. Most systems have filename # length limitation of 255. Path takes extra chars. - filename = (self._storage_max_filename_length(temp_storage) - 4) * 'a' # 4 chars for extension. + filename = ( + self._storage_max_filename_length(temp_storage) - 4 + ) * "a" # 4 chars for extension. obj = Storage() - obj.extended_length.save('%s.txt' % filename, ContentFile('Same Content')) - self.assertEqual(obj.extended_length.name, 'tests/%s.txt' % filename) - self.assertEqual(obj.extended_length.read(), b'Same Content') + obj.extended_length.save("%s.txt" % filename, ContentFile("Same Content")) + self.assertEqual(obj.extended_length.name, "tests/%s.txt" % filename) + self.assertEqual(obj.extended_length.read(), b"Same Content") obj.extended_length.close() def test_filefield_default(self): # Default values allow an object to access a single file. - temp_storage.save('tests/default.txt', ContentFile('default content')) + temp_storage.save("tests/default.txt", ContentFile("default content")) obj = Storage.objects.create() self.assertEqual(obj.default.name, "tests/default.txt") self.assertEqual(obj.default.read(), b"default content") @@ -828,17 +876,17 @@ class FileFieldStorageTests(TestCase): def test_empty_upload_to(self): # upload_to can be empty, meaning it does not use subdirectory. obj = Storage() - obj.empty.save('django_test.txt', ContentFile('more content')) + obj.empty.save("django_test.txt", ContentFile("more content")) self.assertEqual(obj.empty.name, "django_test.txt") self.assertEqual(obj.empty.read(), b"more content") obj.empty.close() def test_pathlib_upload_to(self): obj = Storage() - obj.pathlib_callable.save('some_file1.txt', ContentFile('some content')) - self.assertEqual(obj.pathlib_callable.name, 'bar/some_file1.txt') - obj.pathlib_direct.save('some_file2.txt', ContentFile('some content')) - self.assertEqual(obj.pathlib_direct.name, 'bar/some_file2.txt') + obj.pathlib_callable.save("some_file1.txt", ContentFile("some content")) + self.assertEqual(obj.pathlib_callable.name, "bar/some_file1.txt") + obj.pathlib_direct.save("some_file2.txt", ContentFile("some content")) + self.assertEqual(obj.pathlib_direct.name, "bar/some_file2.txt") obj.random.close() def test_random_upload_to(self): @@ -869,32 +917,34 @@ class FileFieldStorageTests(TestCase): def test_file_object(self): # Create sample file - temp_storage.save('tests/example.txt', ContentFile('some content')) + temp_storage.save("tests/example.txt", ContentFile("some content")) # Load it as Python file object - with open(temp_storage.path('tests/example.txt')) as file_obj: + with open(temp_storage.path("tests/example.txt")) as file_obj: # Save it using storage and read its content - temp_storage.save('tests/file_obj', file_obj) - self.assertTrue(temp_storage.exists('tests/file_obj')) - with temp_storage.open('tests/file_obj') as f: - self.assertEqual(f.read(), b'some content') + temp_storage.save("tests/file_obj", file_obj) + self.assertTrue(temp_storage.exists("tests/file_obj")) + with temp_storage.open("tests/file_obj") as f: + self.assertEqual(f.read(), b"some content") def test_stringio(self): # Test passing StringIO instance as content argument to save output = StringIO() - output.write('content') + output.write("content") output.seek(0) # Save it and read written file - temp_storage.save('tests/stringio', output) - self.assertTrue(temp_storage.exists('tests/stringio')) - with temp_storage.open('tests/stringio') as f: - self.assertEqual(f.read(), b'content') + temp_storage.save("tests/stringio", output) + self.assertTrue(temp_storage.exists("tests/stringio")) + with temp_storage.open("tests/stringio") as f: + self.assertEqual(f.read(), b"content") class FieldCallableFileStorageTests(SimpleTestCase): def setUp(self): - self.temp_storage_location = tempfile.mkdtemp(suffix='filefield_callable_storage') + self.temp_storage_location = tempfile.mkdtemp( + suffix="filefield_callable_storage" + ) def tearDown(self): shutil.rmtree(self.temp_storage_location) @@ -902,7 +952,8 @@ class FieldCallableFileStorageTests(SimpleTestCase): def test_callable_base_class_error_raises(self): class NotStorage: pass - msg = 'FileField.storage must be a subclass/instance of django.core.files.storage.Storage' + + msg = "FileField.storage must be a subclass/instance of django.core.files.storage.Storage" for invalid_type in (NotStorage, str, list, set, tuple): with self.subTest(invalid_type=invalid_type): with self.assertRaisesMessage(TypeError, msg): @@ -939,8 +990,8 @@ class FieldCallableFileStorageTests(SimpleTestCase): Deconstructing gives the original callable, not the evaluated value. """ obj = Storage() - *_, kwargs = obj._meta.get_field('storage_callable').deconstruct() - storage = kwargs['storage'] + *_, kwargs = obj._meta.get_field("storage_callable").deconstruct() + storage = kwargs["storage"] self.assertIs(storage, callable_storage) @@ -948,6 +999,7 @@ class FieldCallableFileStorageTests(SimpleTestCase): # This is written in such a way that it'll always pass on platforms # without threading. + class SlowFile(ContentFile): def chunks(self): time.sleep(1) @@ -958,7 +1010,7 @@ class FileSaveRaceConditionTest(SimpleTestCase): def setUp(self): self.storage_dir = tempfile.mkdtemp() self.storage = FileSystemStorage(self.storage_dir) - self.thread = threading.Thread(target=self.save_file, args=['conflict']) + self.thread = threading.Thread(target=self.save_file, args=["conflict"]) def tearDown(self): shutil.rmtree(self.storage_dir) @@ -968,14 +1020,16 @@ class FileSaveRaceConditionTest(SimpleTestCase): def test_race_condition(self): self.thread.start() - self.save_file('conflict') + self.save_file("conflict") self.thread.join() files = sorted(os.listdir(self.storage_dir)) - self.assertEqual(files[0], 'conflict') - self.assertRegex(files[1], 'conflict_%s' % FILE_SUFFIX_REGEX) + self.assertEqual(files[0], "conflict") + self.assertRegex(files[1], "conflict_%s" % FILE_SUFFIX_REGEX) -@unittest.skipIf(sys.platform == 'win32', "Windows only partially supports umasks and chmod.") +@unittest.skipIf( + sys.platform == "win32", "Windows only partially supports umasks and chmod." +) class FileStoragePermissions(unittest.TestCase): def setUp(self): self.umask = 0o027 @@ -1003,7 +1057,7 @@ class FileStoragePermissions(unittest.TestCase): @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o765) def test_file_upload_directory_permissions(self): self.storage = FileSystemStorage(self.storage_dir) - name = self.storage.save('the_directory/subdir/the_file', ContentFile('data')) + name = self.storage.save("the_directory/subdir/the_file", ContentFile("data")) file_path = Path(self.storage.path(name)) self.assertEqual(file_path.parent.stat().st_mode & 0o777, 0o765) self.assertEqual(file_path.parent.parent.stat().st_mode & 0o777, 0o765) @@ -1011,7 +1065,7 @@ class FileStoragePermissions(unittest.TestCase): @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=None) def test_file_upload_directory_default_permissions(self): self.storage = FileSystemStorage(self.storage_dir) - name = self.storage.save('the_directory/subdir/the_file', ContentFile('data')) + name = self.storage.save("the_directory/subdir/the_file", ContentFile("data")) file_path = Path(self.storage.path(name)) expected_mode = 0o777 & ~self.umask self.assertEqual(file_path.parent.stat().st_mode & 0o777, expected_mode) @@ -1033,30 +1087,29 @@ class FileStoragePathParsing(SimpleTestCase): sure we still mangle the file name instead of the directory name. """ - self.storage.save('dotted.path/test', ContentFile("1")) - self.storage.save('dotted.path/test', ContentFile("2")) + self.storage.save("dotted.path/test", ContentFile("1")) + self.storage.save("dotted.path/test", ContentFile("2")) - files = sorted(os.listdir(os.path.join(self.storage_dir, 'dotted.path'))) - self.assertFalse(os.path.exists(os.path.join(self.storage_dir, 'dotted_.path'))) - self.assertEqual(files[0], 'test') - self.assertRegex(files[1], 'test_%s' % FILE_SUFFIX_REGEX) + files = sorted(os.listdir(os.path.join(self.storage_dir, "dotted.path"))) + self.assertFalse(os.path.exists(os.path.join(self.storage_dir, "dotted_.path"))) + self.assertEqual(files[0], "test") + self.assertRegex(files[1], "test_%s" % FILE_SUFFIX_REGEX) def test_first_character_dot(self): """ File names with a dot as their first character don't have an extension, and the underscore should get added to the end. """ - self.storage.save('dotted.path/.test', ContentFile("1")) - self.storage.save('dotted.path/.test', ContentFile("2")) + self.storage.save("dotted.path/.test", ContentFile("1")) + self.storage.save("dotted.path/.test", ContentFile("2")) - files = sorted(os.listdir(os.path.join(self.storage_dir, 'dotted.path'))) - self.assertFalse(os.path.exists(os.path.join(self.storage_dir, 'dotted_.path'))) - self.assertEqual(files[0], '.test') - self.assertRegex(files[1], '.test_%s' % FILE_SUFFIX_REGEX) + files = sorted(os.listdir(os.path.join(self.storage_dir, "dotted.path"))) + self.assertFalse(os.path.exists(os.path.join(self.storage_dir, "dotted_.path"))) + self.assertEqual(files[0], ".test") + self.assertRegex(files[1], ".test_%s" % FILE_SUFFIX_REGEX) class ContentFileStorageTestCase(unittest.TestCase): - def setUp(self): self.storage_dir = tempfile.mkdtemp() self.storage = FileSystemStorage(self.storage_dir) @@ -1069,11 +1122,11 @@ class ContentFileStorageTestCase(unittest.TestCase): ContentFile can be saved correctly with the filesystem storage, if it was initialized with either bytes or unicode content. """ - self.storage.save('bytes.txt', ContentFile(b"content")) - self.storage.save('unicode.txt', ContentFile("español")) + self.storage.save("bytes.txt", ContentFile(b"content")) + self.storage.save("unicode.txt", ContentFile("español")) -@override_settings(ROOT_URLCONF='file_storage.urls') +@override_settings(ROOT_URLCONF="file_storage.urls") class FileLikeObjectTestCase(LiveServerTestCase): """ Test file-like objects (#15644). @@ -1093,10 +1146,10 @@ class FileLikeObjectTestCase(LiveServerTestCase): Test the File storage API with a file-like object coming from urllib.request.urlopen(). """ - file_like_object = urlopen(self.live_server_url + '/') + file_like_object = urlopen(self.live_server_url + "/") f = File(file_like_object) stored_filename = self.storage.save("remote_file.html", f) - remote_file = urlopen(self.live_server_url + '/') + remote_file = urlopen(self.live_server_url + "/") with self.storage.open(stored_filename) as stored_file: self.assertEqual(stored_file.read(), remote_file.read()) diff --git a/tests/file_storage/urls.py b/tests/file_storage/urls.py index 24c5dcbc56..cf13ab9601 100644 --- a/tests/file_storage/urls.py +++ b/tests/file_storage/urls.py @@ -2,5 +2,5 @@ from django.http import HttpResponse from django.urls import path urlpatterns = [ - path('', lambda req: HttpResponse('example view')), + path("", lambda req: HttpResponse("example view")), ] |
