summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPindi Albert <pindi.albert@gmail.com>2012-12-14 13:48:23 -0800
committerJohannes Linke <johannes.linke@posteo.de>2015-09-06 09:30:24 +0200
commit3bfed737341e87d9f1edd1beac3e7d0eebed3aeb (patch)
tree18fcfef71280d18210c8e100fdbf8531cd84ec5a
parentad49d9901dc67ee9bafff76e750326739a903a85 (diff)
downloaddjango-compressor-3bfed737341e87d9f1edd1beac3e7d0eebed3aeb.tar.gz
Only cache precompilers specified in COMPRESS_CACHEABLE_PRECOMPILERS setting, and refactor caching logic into new CachedCompilerFilter class
-rw-r--r--compressor/base.py8
-rw-r--r--compressor/cache.py4
-rw-r--r--compressor/conf.py1
-rw-r--r--compressor/filters/__init__.py2
-rw-r--r--compressor/filters/base.py33
-rw-r--r--compressor/tests/test_filters.py19
6 files changed, 49 insertions, 18 deletions
diff --git a/compressor/base.py b/compressor/base.py
index 54b16f3..98b98b8 100644
--- a/compressor/base.py
+++ b/compressor/base.py
@@ -20,7 +20,7 @@ from compressor.cache import get_hexdigest, get_mtime
from compressor.conf import settings
from compressor.exceptions import (CompressorError, UncompressableFileError,
FilterDoesNotExist)
-from compressor.filters import CompilerFilter
+from compressor.filters import CachedCompilerFilter
from compressor.storage import compressor_file_storage
from compressor.signals import post_compress
from compressor.utils import get_class, get_mod_func, staticfiles
@@ -254,9 +254,9 @@ class Compressor(object):
try:
mod = import_module(mod_name)
except (ImportError, TypeError):
- filter = CompilerFilter(
- content, filter_type=self.type, filename=filename,
- charset=charset, command=filter_or_command)
+ filter = CachedCompilerFilter(
+ content=content, filter_type=self.type, filename=filename,
+ charset=charset, command=filter_or_command, mimetype=mimetype)
return True, filter.input(**kwargs)
try:
precompiler_class = getattr(mod, cls_name)
diff --git a/compressor/cache.py b/compressor/cache.py
index f80bf54..45942de 100644
--- a/compressor/cache.py
+++ b/compressor/cache.py
@@ -135,6 +135,10 @@ def get_hashed_content(filename, length=12):
return get_hexdigest(file.read(), length)
+def get_precompiler_cachekey(command, contents):
+ return hashlib.sha1('precompiler.%s.%s' % (command, contents)).hexdigest()
+
+
def cache_get(key):
packed_val = cache.get(key)
if packed_val is None:
diff --git a/compressor/conf.py b/compressor/conf.py
index 87f9d69..a546115 100644
--- a/compressor/conf.py
+++ b/compressor/conf.py
@@ -35,6 +35,7 @@ class CompressorConf(AppConf):
# ('text/stylus', 'stylus < {infile} > {outfile}'),
# ('text/x-scss', 'sass --scss {infile} {outfile}'),
)
+ CACHEABLE_PRECOMPILERS = ()
CLOSURE_COMPILER_BINARY = 'java -jar compiler.jar'
CLOSURE_COMPILER_ARGUMENTS = ''
CSSTIDY_BINARY = 'csstidy'
diff --git a/compressor/filters/__init__.py b/compressor/filters/__init__.py
index cd317fa..efeee86 100644
--- a/compressor/filters/__init__.py
+++ b/compressor/filters/__init__.py
@@ -1,3 +1,3 @@
# flake8: noqa
from compressor.filters.base import (FilterBase, CallbackOutputFilter,
- CompilerFilter, FilterError)
+ CompilerFilter, CachedCompilerFilter, FilterError)
diff --git a/compressor/filters/base.py b/compressor/filters/base.py
index cf98999..4a8c27c 100644
--- a/compressor/filters/base.py
+++ b/compressor/filters/base.py
@@ -1,11 +1,9 @@
from __future__ import absolute_import, unicode_literals
import io
-import hashlib
import logging
import subprocess
from platform import system
-from django.core.cache import get_cache
if system() != "Windows":
try:
@@ -29,6 +27,8 @@ except ImportError:
from django.utils.encoding import smart_text
from django.utils import six
+from compressor.cache import cache, get_precompiler_cachekey
+
from compressor.conf import settings
from compressor.exceptions import FilterError
from compressor.utils import get_mod_func
@@ -36,8 +36,6 @@ from compressor.utils import get_mod_func
logger = logging.getLogger("compressor.filters")
-cache = get_cache(settings.COMPRESS_CACHE_BACKEND)
-
class FilterBase(object):
"""
@@ -144,10 +142,6 @@ class CompilerFilter(FilterBase):
self.infile = self.outfile = None
def input(self, **kwargs):
- content_hash = hashlib.sha1(self.command + self.content.encode('utf8')).hexdigest()
- data = cache.get(content_hash)
- if data:
- return data
encoding = self.default_encoding
options = dict(self.options)
@@ -217,5 +211,26 @@ class CompilerFilter(FilterBase):
self.infile.close()
if self.outfile is not None:
self.outfile.close()
- cache.set(content_hash, filtered, settings.COMPRESS_REBUILD_TIMEOUT)
return smart_text(filtered)
+
+
+class CachedCompilerFilter(CompilerFilter):
+
+ def __init__(self, mimetype, **kwargs):
+ self.mimetype = mimetype
+ super(CachedCompilerFilter, self).__init__(**kwargs)
+
+ def input(self, **kwargs):
+ if self.mimetype in settings.COMPRESS_CACHEABLE_PRECOMPILERS:
+ key = self.get_cache_key()
+ data = cache.get(key)
+ if data:
+ return data
+ filtered = super(CachedCompilerFilter, self).input(**kwargs)
+ cache.set(key, filtered, settings.COMPRESS_REBUILD_TIMEOUT)
+ return filtered
+ else:
+ return super(CachedCompilerFilter, self).input(**kwargs)
+
+ def get_cache_key(self):
+ return get_precompiler_cachekey(self.command, self.content.encode('utf8'))
diff --git a/compressor/tests/test_filters.py b/compressor/tests/test_filters.py
index af53f8c..f96bf91 100644
--- a/compressor/tests/test_filters.py
+++ b/compressor/tests/test_filters.py
@@ -14,7 +14,7 @@ from compressor.cache import get_hashed_mtime, get_hashed_content
from compressor.conf import settings
from compressor.css import CssCompressor
from compressor.utils import find_command
-from compressor.filters.base import CompilerFilter
+from compressor.filters.base import CompilerFilter, CachedCompilerFilter
from compressor.filters.cssmin import CSSMinFilter, rCSSMinFilter
from compressor.filters.css_default import CssAbsoluteFilter
from compressor.filters.jsmin import JSMinFilter
@@ -51,6 +51,7 @@ class PrecompilerTestCase(TestCase):
def setUp(self):
self.test_precompiler = os.path.join(test_dir, 'precompiler.py')
self.setup_infile()
+ settings.COMPRESS_CACHEABLE_PRECOMPILERS = ('text/css',)
def setup_infile(self, filename='static/css/one.css'):
self.filename = os.path.join(test_dir, filename)
@@ -104,18 +105,28 @@ class PrecompilerTestCase(TestCase):
def test_precompiler_cache(self):
command = '%s %s -f {infile} -o {outfile}' % (sys.executable, self.test_precompiler)
- compiler = CompilerFilter(content=self.content, filename=self.filename, command=command)
+ compiler = CachedCompilerFilter(content=self.content, filename=self.filename, command=command, mimetype='text/css')
self.assertEqual(u"body { color:#990; }", compiler.input())
# We tell whether the precompiler actually ran by inspecting compiler.infile. If not None, the compiler had to
# write the input out to the file for the external command. If None, it was in the cache and thus skipped.
self.assertIsNotNone(compiler.infile) # Not cached
- compiler = CompilerFilter(content=self.content, filename=self.filename, command=command)
+ compiler = CachedCompilerFilter(content=self.content, filename=self.filename, command=command, mimetype='text/css')
self.assertEqual(u"body { color:#990; }", compiler.input())
self.assertIsNone(compiler.infile) # Cached
self.content += ' ' # Invalidate cache by slightly changing content
- compiler = CompilerFilter(content=self.content, filename=self.filename, command=command)
+ compiler = CachedCompilerFilter(content=self.content, filename=self.filename, command=command, mimetype='text/css')
+ self.assertEqual(u"body { color:#990; }", compiler.input())
+ self.assertIsNotNone(compiler.infile) # Not cached
+
+ def test_precompiler_not_cacheable(self):
+ command = '%s %s -f {infile} -o {outfile}' % (sys.executable, self.test_precompiler)
+ compiler = CachedCompilerFilter(content=self.content, filename=self.filename, command=command, mimetype='text/different')
+ self.assertEqual(u"body { color:#990; }", compiler.input())
+ self.assertIsNotNone(compiler.infile) # Not cached
+
+ compiler = CachedCompilerFilter(content=self.content, filename=self.filename, command=command, mimetype='text/different')
self.assertEqual(u"body { color:#990; }", compiler.input())
self.assertIsNotNone(compiler.infile) # Not cached