Refs #23832 -- Removed deprecated non-timezone aware Storage API.
This commit is contained in:
parent
740f63a3df
commit
2d7fb77987
|
@ -1,6 +1,5 @@
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import warnings
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
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._os import abspathu, safe_join
|
||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
from django.utils.deconstruct import deconstructible
|
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.encoding import filepath_to_uri, force_text
|
||||||
from django.utils.functional import LazyObject, cached_property
|
from django.utils.functional import LazyObject, cached_property
|
||||||
from django.utils.module_loading import import_string
|
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')
|
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):
|
def get_accessed_time(self, name):
|
||||||
"""
|
"""
|
||||||
Return the last accessed time (as a datetime) of the file specified by
|
Return the last accessed time (as a datetime) of the file specified by
|
||||||
name. The datetime will be timezone-aware if USE_TZ=True.
|
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')
|
||||||
# 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)
|
|
||||||
|
|
||||||
def get_created_time(self, name):
|
def get_created_time(self, name):
|
||||||
"""
|
"""
|
||||||
Return the creation time (as a datetime) of the file specified by name.
|
Return the creation time (as a datetime) of the file specified by name.
|
||||||
The datetime will be timezone-aware if USE_TZ=True.
|
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')
|
||||||
# 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)
|
|
||||||
|
|
||||||
def get_modified_time(self, name):
|
def get_modified_time(self, name):
|
||||||
"""
|
"""
|
||||||
Return the last modified time (as a datetime) of the file specified by
|
Return the last modified time (as a datetime) of the file specified by
|
||||||
name. The datetime will be timezone-aware if USE_TZ=True.
|
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')
|
||||||
# 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
|
|
||||||
|
|
||||||
|
|
||||||
@deconstructible
|
@deconstructible
|
||||||
|
@ -415,33 +336,6 @@ class FileSystemStorage(Storage):
|
||||||
url = url.lstrip('/')
|
url = url.lstrip('/')
|
||||||
return urljoin(self.base_url, url)
|
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):
|
def _datetime_from_timestamp(self, ts):
|
||||||
"""
|
"""
|
||||||
If timezone support is enabled, make an aware datetime object in UTC;
|
If timezone support is enabled, make an aware datetime object in UTC;
|
||||||
|
|
|
@ -77,28 +77,6 @@ The ``Storage`` class
|
||||||
used will be the current value of ``os.environ['TZ']``; note that this
|
used will be the current value of ``os.environ['TZ']``; note that this
|
||||||
is usually set from Django's :setting:`TIME_ZONE`.
|
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)
|
.. method:: delete(name)
|
||||||
|
|
||||||
Deletes the file referenced by ``name``. If deletion is not supported
|
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
|
storage systems that aren't able to provide such a listing, this will
|
||||||
raise a ``NotImplementedError`` instead.
|
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')
|
.. method:: open(name, mode='rb')
|
||||||
|
|
||||||
Opens the file given by ``name``. Note that although the returned file
|
Opens the file given by ``name``. Note that although the returned file
|
||||||
|
|
|
@ -347,3 +347,6 @@ these features.
|
||||||
migrations.
|
migrations.
|
||||||
|
|
||||||
* The template ``Context.has_key()`` method is removed.
|
* 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.
|
||||||
|
|
|
@ -20,14 +20,12 @@ from django.core.files.uploadedfile import (
|
||||||
)
|
)
|
||||||
from django.db.models.fields.files import FileDescriptor
|
from django.db.models.fields.files import FileDescriptor
|
||||||
from django.test import (
|
from django.test import (
|
||||||
LiveServerTestCase, SimpleTestCase, TestCase, ignore_warnings,
|
LiveServerTestCase, SimpleTestCase, TestCase, override_settings,
|
||||||
override_settings,
|
|
||||||
)
|
)
|
||||||
from django.test.utils import requires_tz_support
|
from django.test.utils import requires_tz_support
|
||||||
from django.urls import NoReverseMatch, reverse_lazy
|
from django.urls import NoReverseMatch, reverse_lazy
|
||||||
from django.utils import six, timezone
|
from django.utils import six, timezone
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.deprecation import RemovedInDjango20Warning
|
|
||||||
from django.utils.six.moves.urllib.request import urlopen
|
from django.utils.six.moves.urllib.request import urlopen
|
||||||
|
|
||||||
from .models import Storage, temp_storage, temp_storage_location
|
from .models import Storage, temp_storage, temp_storage_location
|
||||||
|
@ -227,21 +225,6 @@ class FileStorageTests(SimpleTestCase):
|
||||||
def test_file_get_accessed_time_timezone(self):
|
def test_file_get_accessed_time_timezone(self):
|
||||||
self._test_file_time_getter(self.storage.get_accessed_time)
|
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):
|
def test_file_get_created_time(self):
|
||||||
"""
|
"""
|
||||||
File storage returns a datetime for the creation time of a file.
|
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):
|
def test_file_get_created_time_timezone(self):
|
||||||
self._test_file_time_getter(self.storage.get_created_time)
|
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):
|
def test_file_get_modified_time(self):
|
||||||
"""
|
"""
|
||||||
File storage returns a datetime for the last modified time of a file.
|
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):
|
def test_file_get_modified_time_timezone(self):
|
||||||
self._test_file_time_getter(self.storage.get_modified_time)
|
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):
|
def test_file_save_without_name(self):
|
||||||
"""
|
"""
|
||||||
File storage extracts the filename from the content object if no
|
File storage extracts the filename from the content object if no
|
||||||
|
@ -613,26 +566,6 @@ class CustomStorageTests(FileStorageTests):
|
||||||
self.storage.delete(second)
|
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):
|
class DiscardingFalseContentStorage(FileSystemStorage):
|
||||||
def _save(self, name, content):
|
def _save(self, name, content):
|
||||||
if content:
|
if content:
|
||||||
|
|
Loading…
Reference in New Issue