Skip to content

Commit

Permalink
Fixed #19670 -- Applied CachedFilesMixin patterns to specific extensions
Browse files Browse the repository at this point in the history
Thanks Simon Meers for the initial patch, and Tim Graham for the review.
  • Loading branch information
claudep committed Mar 30, 2016
1 parent 940b7fd commit edcecaf
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Normalize line endings to avoid spurious failures in the core test suite on Windows.
*html text eol=lf
*css text eol=lf
*js text eol=lf
tests/staticfiles_tests/apps/test/static/test/*txt text eol=lf
tests/staticfiles_tests/project/documents/test/*txt text eol=lf
docs/releases/*.txt merge=union
16 changes: 9 additions & 7 deletions django/contrib/staticfiles/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from django.core.files.storage import FileSystemStorage, get_storage_class
from django.utils.encoding import force_bytes, force_text
from django.utils.functional import LazyObject
from django.utils.six import iteritems
from django.utils.six.moves.urllib.parse import (
unquote, urldefrag, urlsplit, urlunsplit,
)
Expand Down Expand Up @@ -248,13 +249,14 @@ def path_level(name):
# ..to apply each replacement pattern to the content
if name in adjustable_paths:
content = original_file.read().decode(settings.FILE_CHARSET)
for patterns in self._patterns.values():
for pattern, template in patterns:
converter = self.url_converter(name, template)
try:
content = pattern.sub(converter, content)
except ValueError as exc:
yield name, None, exc
for extension, patterns in iteritems(self._patterns):
if matches_patterns(path, (extension,)):
for pattern, template in patterns:
converter = self.url_converter(name, template)
try:
content = pattern.sub(converter, content)
except ValueError as exc:
yield name, None, exc
if hashed_file_exists:
self.delete(hashed_name)
# then save the processed result
Expand Down
1 change: 1 addition & 0 deletions tests/staticfiles_tests/project/documents/cached/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
myVar = url("import.css");
14 changes: 14 additions & 0 deletions tests/staticfiles_tests/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,17 @@ class SimpleCachedStaticFilesStorage(CachedStaticFilesStorage):

def file_hash(self, name, content=None):
return 'deploy12345'


class ExtraPatternsCachedStaticFilesStorage(CachedStaticFilesStorage):
"""
A storage class to test pattern substitutions with more than one pattern
entry. The added pattern rewrites strings like "url(...)" to JS_URL("...").
"""
patterns = tuple(CachedStaticFilesStorage.patterns) + (
(
"*.js", (
(r"""(url\(['"]{0,1}\s*(.*?)["']{0,1}\))""", 'JS_URL("%s")'),
),
),
)
36 changes: 36 additions & 0 deletions tests/staticfiles_tests/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,38 @@ def test_cache_key_memcache_validation(self):
self.assertEqual(cache_key, 'staticfiles:821ea71ef36f95b3922a77f7364670e7')


@override_settings(
STATICFILES_STORAGE='staticfiles_tests.storage.ExtraPatternsCachedStaticFilesStorage',
)
class TestExtraPatternsCachedStorage(CollectionTestCase):

def setUp(self):
storage.staticfiles_storage.hashed_files.clear() # avoid cache interference
super(TestExtraPatternsCachedStorage, self).setUp()

def cached_file_path(self, path):
fullpath = self.render_template(self.static_template_snippet(path))
return fullpath.replace(settings.STATIC_URL, '')

def test_multi_extension_patterns(self):
"""
With storage classes having several file extension patterns, only the
files matching a specific file pattern should be affected by the
substitution (#19670).
"""
# CSS files shouldn't be touched by JS patterns.
relpath = self.cached_file_path("cached/import.css")
self.assertEqual(relpath, "cached/import.2b1d40b0bbd4.css")
with storage.staticfiles_storage.open(relpath) as relfile:
self.assertIn(b'import url("styles.bb84a0240107.css")', relfile.read())

# Confirm JS patterns have been applied to JS files.
relpath = self.cached_file_path("cached/test.js")
self.assertEqual(relpath, "cached/test.62789ffcd280.js")
with storage.staticfiles_storage.open(relpath) as relfile:
self.assertIn(b'JS_URL("import.2b1d40b0bbd4.css")', relfile.read())


@override_settings(
STATICFILES_STORAGE='django.contrib.staticfiles.storage.ManifestStaticFilesStorage',
)
Expand Down Expand Up @@ -320,6 +352,10 @@ class TestCollectionSimpleCachedStorage(CollectionTestCase):
"""
hashed_file_path = hashed_file_path

def setUp(self):
storage.staticfiles_storage.hashed_files.clear() # avoid cache interference
super(TestCollectionSimpleCachedStorage, self).setUp()

def test_template_tag_return(self):
"""
Test the CachedStaticFilesStorage backend.
Expand Down

0 comments on commit edcecaf

Please sign in to comment.