Loading django/contrib/staticfiles/management/commands/collectstatic.py +3 −4 Original line number Diff line number Diff line Loading @@ -237,15 +237,14 @@ class Command(BaseCommand): if self.storage.exists(prefixed_path): try: # When was the target file modified last time? target_last_modified = \ self.storage.modified_time(prefixed_path) target_last_modified = self.storage.get_modified_time(prefixed_path) except (OSError, NotImplementedError, AttributeError): # The storage doesn't support ``modified_time`` or failed # The storage doesn't support get_modified_time() or failed pass else: try: # When was the source file modified last time? source_last_modified = source_storage.modified_time(path) source_last_modified = source_storage.get_modified_time(path) except (OSError, NotImplementedError, AttributeError): pass else: Loading django/core/files/storage.py +121 −3 Original line number Diff line number Diff line import errno import os import warnings from datetime import datetime from django.conf import settings Loading @@ -7,9 +8,11 @@ from django.core.exceptions import SuspiciousFileOperation from django.core.files import File, locks from django.core.files.move import file_move_safe from django.core.signals import setting_changed 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 Loading Loading @@ -140,24 +143,101 @@ class Storage(object): def accessed_time(self, name): """ Returns the last accessed time (as datetime object) of the file specified by name. 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. 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. 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) 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) 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 @deconstructible class FileSystemStorage(Storage): Loading Loading @@ -328,14 +408,52 @@ class FileSystemStorage(Storage): return urljoin(self.base_url, filepath_to_uri(name)) 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; otherwise make a naive one in the local timezone. """ if settings.USE_TZ: # Safe to use .replace() because UTC doesn't have DST return datetime.utcfromtimestamp(ts).replace(tzinfo=timezone.utc) else: return datetime.fromtimestamp(ts) def get_accessed_time(self, name): return self._datetime_from_timestamp(os.path.getatime(self.path(name))) def get_created_time(self, name): return self._datetime_from_timestamp(os.path.getctime(self.path(name))) def get_modified_time(self, name): return self._datetime_from_timestamp(os.path.getmtime(self.path(name))) def get_storage_class(import_path=None): return import_string(import_path or settings.DEFAULT_FILE_STORAGE) Loading docs/internals/deprecation.txt +3 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,9 @@ details on these changes. * Support for the template ``Context.has_key()`` method will be removed. * Support for the ``django.core.files.storage.Storage.accessed_time()``, ``created_time()``, and ``modified_time()`` methods will be removed. .. _deprecation-removed-in-1.10: 1.10 Loading docs/ref/files/storage.txt +48 −4 Original line number Diff line number Diff line Loading @@ -73,10 +73,9 @@ The ``Storage`` class as necessary. .. note:: For methods returning naive ``datetime`` objects, the effective timezone used will be the current value of ``os.environ['TZ']``; note that this is usually set from Django's :setting:`TIME_ZONE`. When methods return naive ``datetime`` objects, the effective timezone 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) Loading @@ -85,6 +84,10 @@ The ``Storage`` class 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 Loading @@ -92,6 +95,10 @@ The ``Storage`` class 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 Loading @@ -104,6 +111,17 @@ The ``Storage`` class in the storage system, or ``False`` if the name is available for a new file. .. method:: get_accessed_time(name) .. versionadded:: 1.10 Returns a :class:`~datetime.datetime` of the last accessed time of the file. For storage systems unable to return the last accessed time this will raise :exc:`NotImplementedError`. If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``, otherwise returns a naive ``datetime`` in the local timezone. .. method:: get_available_name(name, max_length=None) Returns a filename based on the ``name`` parameter that's free and Loading @@ -119,6 +137,28 @@ The ``Storage`` class 7 character alphanumeric string is appended to the filename before the extension. .. method:: get_created_time(name) .. versionadded:: 1.10 Returns a :class:`~datetime.datetime` of the creation time of the file. For storage systems unable to return the creation time this will raise :exc:`NotImplementedError`. If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``, otherwise returns a naive ``datetime`` in the local timezone. .. method:: get_modified_time(name) .. versionadded:: 1.10 Returns a :class:`~datetime.datetime` of the last modified time of the file. For storage systems unable to return the last modified time this will raise :exc:`NotImplementedError`. If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``, otherwise returns a naive ``datetime`` in the local timezone. .. method:: get_valid_name(name) Returns a filename based on the ``name`` parameter that's suitable Loading @@ -138,6 +178,10 @@ The ``Storage`` class 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 Loading docs/releases/1.10.txt +22 −1 Original line number Diff line number Diff line Loading @@ -203,7 +203,13 @@ Email File Storage ~~~~~~~~~~~~ * ... * Storage backends now present a timezone-aware API with new methods :meth:`~django.core.files.storage.Storage.get_accessed_time`, :meth:`~django.core.files.storage.Storage.get_created_time`, and :meth:`~django.core.files.storage.Storage.get_modified_time`. They return a timezone-aware ``datetime`` if :setting:`USE_TZ` is ``True`` and a naive ``datetime`` in the local timezone otherwise. File Uploads ~~~~~~~~~~~~ Loading Loading @@ -623,6 +629,21 @@ added in Django 1.9:: This prevents confusion about an assignment resulting in an implicit save. Non-timezone-aware :class:`~django.core.files.storage.Storage` API ------------------------------------------------------------------ The old, non-timezone-aware methods ``accessed_time()``, ``created_time()``, and ``modified_time()`` are deprecated in favor of the new ``get_*_time()`` methods. Third-party storage backends should implement the new methods and mark the old ones as deprecated. Until then, the new ``get_*_time()`` methods on the base :class:`~django.core.files.storage.Storage` class convert ``datetime``\s from the old methods as required and emit a deprecation warning as they do so. Third-party storage backends may retain the old methods as long as they wish to support earlier versions of Django. :mod:`django.contrib.gis` ------------------------- Loading Loading
django/contrib/staticfiles/management/commands/collectstatic.py +3 −4 Original line number Diff line number Diff line Loading @@ -237,15 +237,14 @@ class Command(BaseCommand): if self.storage.exists(prefixed_path): try: # When was the target file modified last time? target_last_modified = \ self.storage.modified_time(prefixed_path) target_last_modified = self.storage.get_modified_time(prefixed_path) except (OSError, NotImplementedError, AttributeError): # The storage doesn't support ``modified_time`` or failed # The storage doesn't support get_modified_time() or failed pass else: try: # When was the source file modified last time? source_last_modified = source_storage.modified_time(path) source_last_modified = source_storage.get_modified_time(path) except (OSError, NotImplementedError, AttributeError): pass else: Loading
django/core/files/storage.py +121 −3 Original line number Diff line number Diff line import errno import os import warnings from datetime import datetime from django.conf import settings Loading @@ -7,9 +8,11 @@ from django.core.exceptions import SuspiciousFileOperation from django.core.files import File, locks from django.core.files.move import file_move_safe from django.core.signals import setting_changed 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 Loading Loading @@ -140,24 +143,101 @@ class Storage(object): def accessed_time(self, name): """ Returns the last accessed time (as datetime object) of the file specified by name. 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. 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. 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) 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) 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 @deconstructible class FileSystemStorage(Storage): Loading Loading @@ -328,14 +408,52 @@ class FileSystemStorage(Storage): return urljoin(self.base_url, filepath_to_uri(name)) 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; otherwise make a naive one in the local timezone. """ if settings.USE_TZ: # Safe to use .replace() because UTC doesn't have DST return datetime.utcfromtimestamp(ts).replace(tzinfo=timezone.utc) else: return datetime.fromtimestamp(ts) def get_accessed_time(self, name): return self._datetime_from_timestamp(os.path.getatime(self.path(name))) def get_created_time(self, name): return self._datetime_from_timestamp(os.path.getctime(self.path(name))) def get_modified_time(self, name): return self._datetime_from_timestamp(os.path.getmtime(self.path(name))) def get_storage_class(import_path=None): return import_string(import_path or settings.DEFAULT_FILE_STORAGE) Loading
docs/internals/deprecation.txt +3 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,9 @@ details on these changes. * Support for the template ``Context.has_key()`` method will be removed. * Support for the ``django.core.files.storage.Storage.accessed_time()``, ``created_time()``, and ``modified_time()`` methods will be removed. .. _deprecation-removed-in-1.10: 1.10 Loading
docs/ref/files/storage.txt +48 −4 Original line number Diff line number Diff line Loading @@ -73,10 +73,9 @@ The ``Storage`` class as necessary. .. note:: For methods returning naive ``datetime`` objects, the effective timezone used will be the current value of ``os.environ['TZ']``; note that this is usually set from Django's :setting:`TIME_ZONE`. When methods return naive ``datetime`` objects, the effective timezone 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) Loading @@ -85,6 +84,10 @@ The ``Storage`` class 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 Loading @@ -92,6 +95,10 @@ The ``Storage`` class 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 Loading @@ -104,6 +111,17 @@ The ``Storage`` class in the storage system, or ``False`` if the name is available for a new file. .. method:: get_accessed_time(name) .. versionadded:: 1.10 Returns a :class:`~datetime.datetime` of the last accessed time of the file. For storage systems unable to return the last accessed time this will raise :exc:`NotImplementedError`. If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``, otherwise returns a naive ``datetime`` in the local timezone. .. method:: get_available_name(name, max_length=None) Returns a filename based on the ``name`` parameter that's free and Loading @@ -119,6 +137,28 @@ The ``Storage`` class 7 character alphanumeric string is appended to the filename before the extension. .. method:: get_created_time(name) .. versionadded:: 1.10 Returns a :class:`~datetime.datetime` of the creation time of the file. For storage systems unable to return the creation time this will raise :exc:`NotImplementedError`. If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``, otherwise returns a naive ``datetime`` in the local timezone. .. method:: get_modified_time(name) .. versionadded:: 1.10 Returns a :class:`~datetime.datetime` of the last modified time of the file. For storage systems unable to return the last modified time this will raise :exc:`NotImplementedError`. If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``, otherwise returns a naive ``datetime`` in the local timezone. .. method:: get_valid_name(name) Returns a filename based on the ``name`` parameter that's suitable Loading @@ -138,6 +178,10 @@ The ``Storage`` class 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 Loading
docs/releases/1.10.txt +22 −1 Original line number Diff line number Diff line Loading @@ -203,7 +203,13 @@ Email File Storage ~~~~~~~~~~~~ * ... * Storage backends now present a timezone-aware API with new methods :meth:`~django.core.files.storage.Storage.get_accessed_time`, :meth:`~django.core.files.storage.Storage.get_created_time`, and :meth:`~django.core.files.storage.Storage.get_modified_time`. They return a timezone-aware ``datetime`` if :setting:`USE_TZ` is ``True`` and a naive ``datetime`` in the local timezone otherwise. File Uploads ~~~~~~~~~~~~ Loading Loading @@ -623,6 +629,21 @@ added in Django 1.9:: This prevents confusion about an assignment resulting in an implicit save. Non-timezone-aware :class:`~django.core.files.storage.Storage` API ------------------------------------------------------------------ The old, non-timezone-aware methods ``accessed_time()``, ``created_time()``, and ``modified_time()`` are deprecated in favor of the new ``get_*_time()`` methods. Third-party storage backends should implement the new methods and mark the old ones as deprecated. Until then, the new ``get_*_time()`` methods on the base :class:`~django.core.files.storage.Storage` class convert ``datetime``\s from the old methods as required and emit a deprecation warning as they do so. Third-party storage backends may retain the old methods as long as they wish to support earlier versions of Django. :mod:`django.contrib.gis` ------------------------- Loading