diff --git a/compressor/base.py b/compressor/base.py
index 5d83044..f47fd83 100644
--- a/compressor/base.py
+++ b/compressor/base.py
@@ -36,7 +36,7 @@ class Compressor(object):
"""
raise NotImplementedError
- def get_filename(self, url):
+ def get_basename(self, url):
try:
base_url = self.storage.base_url
except AttributeError:
@@ -48,6 +48,9 @@ class Compressor(object):
basename = url.replace(base_url, "", 1)
# drop the querystring, which is used for non-compressed cache-busting.
basename = basename.split("?", 1)[0]
+ return basename
+
+ def get_filename(self, basename):
# first try to find it with staticfiles (in debug mode)
filename = None
if settings.DEBUG and self.finders:
@@ -76,7 +79,8 @@ class Compressor(object):
@cached_property
def mtimes(self):
return [str(get_mtime(value))
- for kind, value, _ in self.split_contents() if kind == 'file']
+ for kind, value, _, _ in self.split_contents()
+ if kind == 'file']
@cached_property
def cachekey(self):
@@ -86,10 +90,11 @@ class Compressor(object):
@cached_property
def hunks(self):
- for kind, value, elem in self.split_contents():
+ for kind, value, basename, elem in self.split_contents():
if kind == "hunk":
yield unicode(self.filter(
- value, method="input", elem=elem, kind=kind))
+ value, basename=basename, method="input", elem=elem,
+ kind=kind))
elif kind == "file":
content = ""
fd = open(value, 'rb')
@@ -101,7 +106,8 @@ class Compressor(object):
finally:
fd.close()
content = self.filter(content,
- method="input", filename=value, elem=elem, kind=kind)
+ method="input", filename=value, basename=basename,
+ elem=elem, kind=kind)
attribs = self.parser.elem_attribs(elem)
charset = attribs.get("charset", self.charset)
yield unicode(content, charset)
diff --git a/compressor/css.py b/compressor/css.py
index d7922b5..69116f9 100644
--- a/compressor/css.py
+++ b/compressor/css.py
@@ -1,3 +1,5 @@
+import os
+
from compressor.conf import settings
from compressor.base import Compressor
from compressor.exceptions import UncompressableFileError
@@ -22,13 +24,14 @@ class CssCompressor(Compressor):
elem_attribs = self.parser.elem_attribs(elem)
if elem_name == 'link' and elem_attribs['rel'] == 'stylesheet':
try:
- filename = self.get_filename(elem_attribs['href'])
- data = ('file', filename, elem)
+ basename = self.get_basename(elem_attribs['href'])
+ filename = self.get_filename(basename)
+ data = ('file', filename, basename, elem)
except UncompressableFileError:
if settings.DEBUG:
raise
elif elem_name == 'style':
- data = ('hunk', self.parser.elem_content(elem), elem)
+ data = ('hunk', self.parser.elem_content(elem), None, elem)
if data:
self.split_content.append(data)
media = elem_attribs.get('media', None)
diff --git a/compressor/filters/css_default.py b/compressor/filters/css_default.py
index 8e9a672..5a3cd3e 100644
--- a/compressor/filters/css_default.py
+++ b/compressor/filters/css_default.py
@@ -5,18 +5,20 @@ import posixpath
from compressor.cache import get_hashed_mtime
from compressor.conf import settings
from compressor.filters import FilterBase
+from compressor.utils import staticfiles
URL_PATTERN = re.compile(r'url\(([^\)]+)\)')
class CssAbsoluteFilter(FilterBase):
- def input(self, filename=None, **kwargs):
+ def input(self, filename=None, basename=None, **kwargs):
self.root = os.path.normcase(os.path.abspath(settings.COMPRESS_ROOT))
if filename is not None:
filename = os.path.normcase(os.path.abspath(filename))
- if not filename or not filename.startswith(self.root):
+ if not (filename and filename.startswith(self.root)) and \
+ not self.find(basename):
return self.content
- self.path = filename[len(self.root):].replace(os.sep, '/')
+ self.path = basename.replace(os.sep, '/')
self.path = self.path.lstrip('/')
self.url = settings.COMPRESS_URL.rstrip('/')
self.url_path = self.url
@@ -36,6 +38,10 @@ class CssAbsoluteFilter(FilterBase):
output = URL_PATTERN.sub(self.url_converter, self.content)
return output
+ def find(self, basename):
+ if settings.DEBUG and basename and staticfiles.finders:
+ return staticfiles.finders.find(basename)
+
def guess_filename(self, url):
local_path = url
if self.has_http:
diff --git a/compressor/js.py b/compressor/js.py
index 4657f00..e28b102 100644
--- a/compressor/js.py
+++ b/compressor/js.py
@@ -1,3 +1,5 @@
+import os
+
from compressor.conf import settings
from compressor.base import Compressor
from compressor.exceptions import UncompressableFileError
@@ -19,12 +21,14 @@ class JsCompressor(Compressor):
attribs = self.parser.elem_attribs(elem)
if 'src' in attribs:
try:
+ basename = self.get_basename(attribs['src'])
+ filename = self.get_filename(basename)
self.split_content.append(
- ('file', self.get_filename(attribs['src']), elem))
+ ('file', filename, basename, elem))
except UncompressableFileError:
if settings.DEBUG:
raise
else:
content = self.parser.elem_content(elem)
- self.split_content.append(('hunk', content, elem))
+ self.split_content.append(('hunk', content, None, elem))
return self.split_content
diff --git a/compressor/tests/tests.py b/compressor/tests/tests.py
index 242ab5e..9cd51a4 100644
--- a/compressor/tests/tests.py
+++ b/compressor/tests/tests.py
@@ -55,12 +55,12 @@ class CompressorTestCase(TestCase):
def test_css_split(self):
out = [
- ('file', os.path.join(settings.COMPRESS_ROOT, u'css/one.css'), u''),
- ('hunk', u'p { border:5px solid green;}', u''),
- ('file', os.path.join(settings.COMPRESS_ROOT, u'css/two.css'), u''),
+ ('file', os.path.join(settings.COMPRESS_ROOT, u'css/one.css'), u'css/one.css', u''),
+ ('hunk', u'p { border:5px solid green;}', None, u''),
+ ('file', os.path.join(settings.COMPRESS_ROOT, u'css/two.css'), u'css/two.css', u''),
]
split = self.css_node.split_contents()
- split = [(x[0], x[1], self.css_node.parser.elem_str(x[2])) for x in split]
+ split = [(x[0], x[1], x[2], self.css_node.parser.elem_str(x[3])) for x in split]
self.assertEqual(out, split)
def test_css_hunks(self):
@@ -93,11 +93,11 @@ class CompressorTestCase(TestCase):
self.assertEqual(output, self.css_node.output().strip())
def test_js_split(self):
- out = [('file', os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), ''),
- ('hunk', u'obj.value = "value";', '')
+ out = [('file', os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), u'js/one.js', ''),
+ ('hunk', u'obj.value = "value";', None, '')
]
split = self.js_node.split_contents()
- split = [(x[0], x[1], self.js_node.parser.elem_str(x[2])) for x in split]
+ split = [(x[0], x[1], x[2], self.js_node.parser.elem_str(x[3])) for x in split]
self.assertEqual(out, split)
def test_js_hunks(self):
@@ -164,20 +164,20 @@ class Html5LibParserTests(ParserTestCase, CompressorTestCase):
def test_css_split(self):
out = [
- ('file', os.path.join(settings.COMPRESS_ROOT, u'css/one.css'), u''),
- ('hunk', u'p { border:5px solid green;}', u''),
- ('file', os.path.join(settings.COMPRESS_ROOT, u'css/two.css'), u''),
+ ('file', os.path.join(settings.COMPRESS_ROOT, u'css/one.css'), u'css/one.css', u''),
+ ('hunk', u'p { border:5px solid green;}', None, u''),
+ ('file', os.path.join(settings.COMPRESS_ROOT, u'css/two.css'), u'css/two.css', u''),
]
split = self.css_node.split_contents()
- split = [(x[0], x[1], self.css_node.parser.elem_str(x[2])) for x in split]
+ split = [(x[0], x[1], x[2], self.css_node.parser.elem_str(x[3])) for x in split]
self.assertEqual(out, split)
def test_js_split(self):
- out = [('file', os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), u''),
- ('hunk', u'obj.value = "value";', u'')
+ out = [('file', os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), u'js/one.js', u''),
+ ('hunk', u'obj.value = "value";', None, u'')
]
split = self.js_node.split_contents()
- split = [(x[0], x[1], self.js_node.parser.elem_str(x[2])) for x in split]
+ split = [(x[0], x[1], x[2], self.js_node.parser.elem_str(x[3])) for x in split]
self.assertEqual(out, split)
Html5LibParserTests = skipIf(
@@ -211,11 +211,11 @@ class CssAbsolutizingTestCase(TestCase):
content = "p { background: url('../../images/image.gif') }"
output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename))
filter = CssAbsoluteFilter(content)
- self.assertEqual(output, filter.input(filename=filename))
+ self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css'))
settings.COMPRESS_URL = 'http://media.example.com/'
filename = os.path.join(settings.COMPRESS_ROOT, 'css/url/test.css')
output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename))
- self.assertEqual(output, filter.input(filename=filename))
+ self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css'))
def test_css_absolute_filter_https(self):
from compressor.filters.css_default import CssAbsoluteFilter
@@ -223,11 +223,11 @@ class CssAbsolutizingTestCase(TestCase):
content = "p { background: url('../../images/image.gif') }"
output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename))
filter = CssAbsoluteFilter(content)
- self.assertEqual(output, filter.input(filename=filename))
+ self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css'))
settings.COMPRESS_URL = 'https://media.example.com/'
filename = os.path.join(settings.COMPRESS_ROOT, 'css/url/test.css')
output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename))
- self.assertEqual(output, filter.input(filename=filename))
+ self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css'))
def test_css_absolute_filter_relative_path(self):
from compressor.filters.css_default import CssAbsoluteFilter
@@ -235,10 +235,10 @@ class CssAbsolutizingTestCase(TestCase):
content = "p { background: url('../../images/image.gif') }"
output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename))
filter = CssAbsoluteFilter(content)
- self.assertEqual(output, filter.input(filename=filename))
+ self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css'))
settings.COMPRESS_URL = 'https://media.example.com/'
output = "p { background: url('%simages/image.gif?%s') }" % (settings.COMPRESS_URL, get_hashed_mtime(filename))
- self.assertEqual(output, filter.input(filename=filename))
+ self.assertEqual(output, filter.input(filename=filename, basename='css/url/test.css'))
def test_css_hunks(self):
hash_dict = {