Refs #28606 -- Removed CachedStaticFilesStorage per deprecation timeline.

This commit is contained in:
Mariusz Felisiak 2019-09-06 13:40:59 +02:00
parent 81993b47ea
commit f1894bae30
4 changed files with 3 additions and 178 deletions

View File

@ -3,18 +3,13 @@ import json
import os import os
import posixpath import posixpath
import re import re
import warnings
from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit
from django.conf import settings from django.conf import settings
from django.contrib.staticfiles.utils import check_settings, matches_patterns from django.contrib.staticfiles.utils import check_settings, matches_patterns
from django.core.cache import (
InvalidCacheBackendError, cache as default_cache, caches,
)
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage, get_storage_class from django.core.files.storage import FileSystemStorage, get_storage_class
from django.utils.deprecation import RemovedInDjango31Warning
from django.utils.functional import LazyObject from django.utils.functional import LazyObject
@ -430,63 +425,6 @@ class ManifestFilesMixin(HashedFilesMixin):
return urlunsplit(unparsed_name) return urlunsplit(unparsed_name)
class _MappingCache:
"""
A small dict-like wrapper for a given cache backend instance.
"""
def __init__(self, cache):
self.cache = cache
def __setitem__(self, key, value):
self.cache.set(key, value)
def __getitem__(self, key):
value = self.cache.get(key)
if value is None:
raise KeyError("Couldn't find a file name '%s'" % key)
return value
def clear(self):
self.cache.clear()
def update(self, data):
self.cache.set_many(data)
def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default
class CachedFilesMixin(HashedFilesMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
try:
self.hashed_files = _MappingCache(caches['staticfiles'])
except InvalidCacheBackendError:
# Use the default backend
self.hashed_files = _MappingCache(default_cache)
def hash_key(self, name):
key = hashlib.md5(self.clean_name(name).encode()).hexdigest()
return 'staticfiles:%s' % key
class CachedStaticFilesStorage(CachedFilesMixin, StaticFilesStorage):
"""
A static file system storage backend which also saves
hashed copies of the files it saves.
"""
def __init__(self, *args, **kwargs):
warnings.warn(
'CachedStaticFilesStorage is deprecated in favor of '
'ManifestStaticFilesStorage.',
RemovedInDjango31Warning, stacklevel=2,
)
super().__init__(*args, **kwargs)
class ManifestStaticFilesStorage(ManifestFilesMixin, StaticFilesStorage): class ManifestStaticFilesStorage(ManifestFilesMixin, StaticFilesStorage):
""" """
A static file system storage backend which also saves A static file system storage backend which also saves

View File

@ -363,39 +363,6 @@ hashing algorithm.
.. _`url()`: https://www.w3.org/TR/CSS2/syndata.html#uri .. _`url()`: https://www.w3.org/TR/CSS2/syndata.html#uri
.. _`Cascading Style Sheets`: https://www.w3.org/Style/CSS/ .. _`Cascading Style Sheets`: https://www.w3.org/Style/CSS/
``CachedStaticFilesStorage``
----------------------------
.. class:: storage.CachedStaticFilesStorage
.. deprecated:: 2.2
``CachedStaticFilesStorage`` is deprecated as it has some intractable
problems, some of which are outlined below. Use
:class:`~storage.ManifestStaticFilesStorage` or a third-party cloud storage
instead.
``CachedStaticFilesStorage`` is a similar class like the
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` class
but uses Django's :doc:`caching framework</topics/cache>` for storing the
hashed names of processed files instead of a static manifest file called
``staticfiles.json``. This is mostly useful for situations in which you don't
have access to the file system.
If you want to override certain options of the cache backend the storage uses,
specify a custom entry in the :setting:`CACHES` setting named
``'staticfiles'``. It falls back to using the ``'default'`` cache backend.
.. warning::
``CachedStaticFilesStorage`` isn't recommended -- in almost all cases
``ManifestStaticFilesStorage`` is a better choice. There are several
performance penalties when using ``CachedStaticFilesStorage`` since a cache
miss requires hashing files at runtime. Remote file storage require several
round-trips to hash a file on a cache miss, as several file accesses are
required to ensure that the file hash is correct in the case of nested file
paths.
``ManifestFilesMixin`` ``ManifestFilesMixin``
---------------------- ----------------------

View File

@ -238,3 +238,5 @@ to remove usage of these features.
``django.contrib.postgres.forms.FloatRangeField`` are removed. ``django.contrib.postgres.forms.FloatRangeField`` are removed.
* The ``FILE_CHARSET`` setting is removed. * The ``FILE_CHARSET`` setting is removed.
* ``django.contrib.staticfiles.storage.CachedStaticFilesStorage`` is removed.

View File

@ -11,10 +11,8 @@ from django.contrib.staticfiles import finders, storage
from django.contrib.staticfiles.management.commands.collectstatic import ( from django.contrib.staticfiles.management.commands.collectstatic import (
Command as CollectstaticCommand, Command as CollectstaticCommand,
) )
from django.core.cache.backends.base import BaseCache
from django.core.management import call_command from django.core.management import call_command
from django.test import SimpleTestCase, ignore_warnings, override_settings from django.test import override_settings
from django.utils.deprecation import RemovedInDjango31Warning
from .cases import CollectionTestCase from .cases import CollectionTestCase
from .settings import TEST_ROOT from .settings import TEST_ROOT
@ -231,86 +229,6 @@ class TestHashedFiles:
self.assertPostCondition() self.assertPostCondition()
@ignore_warnings(category=RemovedInDjango31Warning)
@override_settings(
STATICFILES_STORAGE='django.contrib.staticfiles.storage.CachedStaticFilesStorage',
)
class TestCollectionCachedStorage(TestHashedFiles, CollectionTestCase):
"""
Tests for the Cache busting storage
"""
def test_cache_invalidation(self):
name = "cached/styles.css"
hashed_name = "cached/styles.5e0040571e1a.css"
# check if the cache is filled correctly as expected
cache_key = storage.staticfiles_storage.hash_key(name)
cached_name = storage.staticfiles_storage.hashed_files.get(cache_key)
self.assertEqual(self.hashed_file_path(name), cached_name)
# clearing the cache to make sure we re-set it correctly in the url method
storage.staticfiles_storage.hashed_files.clear()
cached_name = storage.staticfiles_storage.hashed_files.get(cache_key)
self.assertIsNone(cached_name)
self.assertEqual(self.hashed_file_path(name), hashed_name)
cached_name = storage.staticfiles_storage.hashed_files.get(cache_key)
self.assertEqual(cached_name, hashed_name)
# Check files that had to be hashed multiple times since their content
# includes other files that were hashed.
name = 'cached/relative.css'
hashed_name = 'cached/relative.c3e9e1ea6f2e.css'
cache_key = storage.staticfiles_storage.hash_key(name)
cached_name = storage.staticfiles_storage.hashed_files.get(cache_key)
self.assertIsNone(cached_name)
self.assertEqual(self.hashed_file_path(name), hashed_name)
cached_name = storage.staticfiles_storage.hashed_files.get(cache_key)
self.assertEqual(cached_name, hashed_name)
def test_cache_key_memcache_validation(self):
"""
Handle cache key creation correctly, see #17861.
"""
name = (
"/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff"
"/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff"
"/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff"
"/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff"
"/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff"
"/some crazy/\x16\xb4"
)
cache_key = storage.staticfiles_storage.hash_key(name)
cache_validator = BaseCache({})
cache_validator.validate_key(cache_key)
self.assertEqual(cache_key, 'staticfiles:821ea71ef36f95b3922a77f7364670e7')
def test_corrupt_intermediate_files(self):
configured_storage = storage.staticfiles_storage
# Clear cache to force rehashing of the files
configured_storage.hashed_files.clear()
# Simulate a corrupt chain of intermediate files by ensuring they don't
# resolve before the max post-process count, which would normally be
# high enough.
configured_storage.max_post_process_passes = 1
# File without intermediates that can be rehashed without a problem.
self.hashed_file_path('cached/css/img/window.png')
# File with too many intermediates to rehash with the low max
# post-process passes.
err_msg = "The name 'cached/styles.css' could not be hashed with %r." % (configured_storage._wrapped,)
with self.assertRaisesMessage(ValueError, err_msg):
self.hashed_file_path('cached/styles.css')
class TestCachedStaticFilesStorageDeprecation(SimpleTestCase):
def test_warning(self):
from django.contrib.staticfiles.storage import CachedStaticFilesStorage
from django.utils.deprecation import RemovedInDjango31Warning
msg = (
'CachedStaticFilesStorage is deprecated in favor of '
'ManifestStaticFilesStorage.'
)
with self.assertRaisesMessage(RemovedInDjango31Warning, msg):
CachedStaticFilesStorage()
@override_settings(STATICFILES_STORAGE='staticfiles_tests.storage.ExtraPatternsStorage') @override_settings(STATICFILES_STORAGE='staticfiles_tests.storage.ExtraPatternsStorage')
class TestExtraPatternsStorage(CollectionTestCase): class TestExtraPatternsStorage(CollectionTestCase):