diff --git a/django/core/files/storage.py b/django/core/files/storage.py index 98c89ddcfa..9cd4196c23 100644 --- a/django/core/files/storage.py +++ b/django/core/files/storage.py @@ -1,6 +1,5 @@ import errno import os -import warnings from datetime import datetime from django.conf import settings @@ -12,7 +11,6 @@ from django.utils import timezone from django.utils._os import abspathu, safe_join from django.utils.crypto import get_random_string from django.utils.deconstruct import deconstructible -from django.utils.deprecation import RemovedInDjango20Warning from django.utils.encoding import filepath_to_uri, force_text from django.utils.functional import LazyObject, cached_property from django.utils.module_loading import import_string @@ -146,103 +144,26 @@ class Storage(object): """ raise NotImplementedError('subclasses of Storage must provide a url() method') - def accessed_time(self, name): - """ - Returns the last accessed time (as datetime object) of the file - specified by name. Deprecated: use get_accessed_time() instead. - """ - warnings.warn( - 'Storage.accessed_time() is deprecated in favor of get_accessed_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - raise NotImplementedError('subclasses of Storage must provide an accessed_time() method') - - def created_time(self, name): - """ - Returns the creation time (as datetime object) of the file - specified by name. Deprecated: use get_created_time() instead. - """ - warnings.warn( - 'Storage.created_time() is deprecated in favor of get_created_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - raise NotImplementedError('subclasses of Storage must provide a created_time() method') - - def modified_time(self, name): - """ - Returns the last modified time (as datetime object) of the file - specified by name. Deprecated: use get_modified_time() instead. - """ - warnings.warn( - 'Storage.modified_time() is deprecated in favor of get_modified_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - raise NotImplementedError('subclasses of Storage must provide a modified_time() method') - def get_accessed_time(self, name): """ Return the last accessed time (as a datetime) of the file specified by name. The datetime will be timezone-aware if USE_TZ=True. """ - # At the end of the deprecation: - # raise NotImplementedError('subclasses of Storage must provide a get_accessed_time() method') - warnings.warn( - 'Storage.accessed_time() is deprecated. ' - 'Storage backends should implement get_accessed_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - dt = self.accessed_time(name) - return _possibly_make_aware(dt) + raise NotImplementedError('subclasses of Storage must provide a get_accessed_time() method') def get_created_time(self, name): """ Return the creation time (as a datetime) of the file specified by name. The datetime will be timezone-aware if USE_TZ=True. """ - # At the end of the deprecation: - # raise NotImplementedError('subclasses of Storage must provide a get_created_time() method') - warnings.warn( - 'Storage.created_time() is deprecated. ' - 'Storage backends should implement get_created_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - dt = self.created_time(name) - return _possibly_make_aware(dt) + raise NotImplementedError('subclasses of Storage must provide a get_created_time() method') def get_modified_time(self, name): """ Return the last modified time (as a datetime) of the file specified by name. The datetime will be timezone-aware if USE_TZ=True. """ - # At the end of the deprecation: - # raise NotImplementedError('subclasses of Storage must provide a get_modified_time() method') - warnings.warn( - 'Storage.modified_time() is deprecated. ' - 'Storage backends should implement get_modified_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - dt = self.modified_time(name) - return _possibly_make_aware(dt) - - -def _possibly_make_aware(dt): - """ - Convert a datetime object in the local timezone to aware - in UTC, if USE_TZ is True. - """ - # This function is only needed to help with the deprecations above and can - # be removed in Django 2.0, RemovedInDjango20Warning. - if settings.USE_TZ: - tz = timezone.get_default_timezone() - return timezone.make_aware(dt, tz).astimezone(timezone.utc) - else: - return dt + raise NotImplementedError('subclasses of Storage must provide a get_modified_time() method') @deconstructible @@ -415,33 +336,6 @@ class FileSystemStorage(Storage): url = url.lstrip('/') return urljoin(self.base_url, url) - def accessed_time(self, name): - warnings.warn( - 'FileSystemStorage.accessed_time() is deprecated in favor of ' - 'get_accessed_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - return datetime.fromtimestamp(os.path.getatime(self.path(name))) - - def created_time(self, name): - warnings.warn( - 'FileSystemStorage.created_time() is deprecated in favor of ' - 'get_created_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - return datetime.fromtimestamp(os.path.getctime(self.path(name))) - - def modified_time(self, name): - warnings.warn( - 'FileSystemStorage.modified_time() is deprecated in favor of ' - 'get_modified_time().', - RemovedInDjango20Warning, - stacklevel=2, - ) - return datetime.fromtimestamp(os.path.getmtime(self.path(name))) - def _datetime_from_timestamp(self, ts): """ If timezone support is enabled, make an aware datetime object in UTC; diff --git a/docs/ref/files/storage.txt b/docs/ref/files/storage.txt index 0e8303c7af..61bf3c3951 100644 --- a/docs/ref/files/storage.txt +++ b/docs/ref/files/storage.txt @@ -77,28 +77,6 @@ The ``Storage`` class used will be the current value of ``os.environ['TZ']``; note that this is usually set from Django's :setting:`TIME_ZONE`. - .. method:: accessed_time(name) - - Returns a naive ``datetime`` object containing the last - accessed time of the file. For storage systems that aren't - able to return the last accessed time this will raise - ``NotImplementedError`` instead. - - .. deprecated:: 1.10 - - Use :meth:`get_accessed_time` instead. - - .. method:: created_time(name) - - Returns a naive ``datetime`` object containing the creation - time of the file. For storage systems that aren't able to - return the creation time this will raise - ``NotImplementedError`` instead. - - .. deprecated:: 1.10 - - Use :meth:`get_created_time` instead. - .. method:: delete(name) Deletes the file referenced by ``name``. If deletion is not supported @@ -186,17 +164,6 @@ The ``Storage`` class storage systems that aren't able to provide such a listing, this will raise a ``NotImplementedError`` instead. - .. method:: modified_time(name) - - Returns a naive ``datetime`` object containing the last - modified time. For storage systems that aren't able to return - the last modified time, this will raise - ``NotImplementedError`` instead. - - .. deprecated:: 1.10 - - Use :meth:`get_modified_time` instead. - .. method:: open(name, mode='rb') Opens the file given by ``name``. Note that although the returned file diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt index c679f6ea85..3bc2199a39 100644 --- a/docs/releases/2.0.txt +++ b/docs/releases/2.0.txt @@ -347,3 +347,6 @@ these features. migrations. * The template ``Context.has_key()`` method is removed. + +* Support for the ``django.core.files.storage.Storage.accessed_time()``, + ``created_time()``, and ``modified_time()`` methods is removed. diff --git a/tests/file_storage/tests.py b/tests/file_storage/tests.py index 3ac6483623..7a8b104665 100644 --- a/tests/file_storage/tests.py +++ b/tests/file_storage/tests.py @@ -20,14 +20,12 @@ from django.core.files.uploadedfile import ( ) from django.db.models.fields.files import FileDescriptor from django.test import ( - LiveServerTestCase, SimpleTestCase, TestCase, ignore_warnings, - override_settings, + LiveServerTestCase, SimpleTestCase, TestCase, override_settings, ) from django.test.utils import requires_tz_support from django.urls import NoReverseMatch, reverse_lazy from django.utils import six, timezone from django.utils._os import upath -from django.utils.deprecation import RemovedInDjango20Warning from django.utils.six.moves.urllib.request import urlopen from .models import Storage, temp_storage, temp_storage_location @@ -227,21 +225,6 @@ class FileStorageTests(SimpleTestCase): def test_file_get_accessed_time_timezone(self): self._test_file_time_getter(self.storage.get_accessed_time) - @ignore_warnings(category=RemovedInDjango20Warning) - def test_file_accessed_time(self): - """ - File storage returns a datetime for the last accessed time of a file. - """ - self.assertFalse(self.storage.exists('test.file')) - - f = ContentFile('custom contents') - f_name = self.storage.save('test.file', f) - self.addCleanup(self.storage.delete, f_name) - atime = self.storage.accessed_time(f_name) - - self.assertEqual(atime, datetime.fromtimestamp(os.path.getatime(self.storage.path(f_name)))) - self.assertLess(datetime.now() - self.storage.accessed_time(f_name), timedelta(seconds=2)) - def test_file_get_created_time(self): """ File storage returns a datetime for the creation time of a file. @@ -260,21 +243,6 @@ class FileStorageTests(SimpleTestCase): def test_file_get_created_time_timezone(self): self._test_file_time_getter(self.storage.get_created_time) - @ignore_warnings(category=RemovedInDjango20Warning) - def test_file_created_time(self): - """ - File storage returns a datetime for the creation time of a file. - """ - self.assertFalse(self.storage.exists('test.file')) - - f = ContentFile('custom contents') - f_name = self.storage.save('test.file', f) - ctime = self.storage.created_time(f_name) - self.addCleanup(self.storage.delete, f_name) - - self.assertEqual(ctime, datetime.fromtimestamp(os.path.getctime(self.storage.path(f_name)))) - self.assertLess(datetime.now() - self.storage.created_time(f_name), timedelta(seconds=2)) - def test_file_get_modified_time(self): """ File storage returns a datetime for the last modified time of a file. @@ -293,21 +261,6 @@ class FileStorageTests(SimpleTestCase): def test_file_get_modified_time_timezone(self): self._test_file_time_getter(self.storage.get_modified_time) - @ignore_warnings(category=RemovedInDjango20Warning) - def test_file_modified_time(self): - """ - File storage returns a datetime for the last modified time of a file. - """ - self.assertFalse(self.storage.exists('test.file')) - - f = ContentFile('custom contents') - f_name = self.storage.save('test.file', f) - self.addCleanup(self.storage.delete, f_name) - mtime = self.storage.modified_time(f_name) - - self.assertEqual(mtime, datetime.fromtimestamp(os.path.getmtime(self.storage.path(f_name)))) - self.assertLess(datetime.now() - self.storage.modified_time(f_name), timedelta(seconds=2)) - def test_file_save_without_name(self): """ File storage extracts the filename from the content object if no @@ -613,26 +566,6 @@ class CustomStorageTests(FileStorageTests): self.storage.delete(second) -class CustomStorageLegacyDatetimeHandling(FileSystemStorage): - # Use the legacy accessed_time() et al from FileSystemStorage and the - # shim get_accessed_time() et al from the Storage baseclass. Both of those - # raise warnings, so the testcase class ignores them all. - - def get_accessed_time(self, name): - return super(FileSystemStorage, self).get_accessed_time(name) - - def get_created_time(self, name): - return super(FileSystemStorage, self).get_created_time(name) - - def get_modified_time(self, name): - return super(FileSystemStorage, self).get_modified_time(name) - - -@ignore_warnings(category=RemovedInDjango20Warning) -class CustomStorageLegacyDatetimeHandlingTests(FileStorageTests): - storage_class = CustomStorageLegacyDatetimeHandling - - class DiscardingFalseContentStorage(FileSystemStorage): def _save(self, name, content): if content: