Files
deb-python-django-compressor/compressor/contrib/jinja2ext.py
2011-09-21 12:16:24 +02:00

86 lines
3.1 KiB
Python

from django.core.exceptions import ImproperlyConfigured
from jinja2 import nodes
from jinja2.ext import Extension
from jinja2.exceptions import TemplateSyntaxError
from compressor.conf import settings
from compressor.utils import get_class
from compressor.templatetags.compress import OUTPUT_FILE
from compressor.cache import (cache_get, cache_set,
get_templatetag_cachekey)
class CompressorExtension(Extension):
tags = set(['compress'])
@property
def compressors(self):
return {
'js': settings.COMPRESS_JS_COMPRESSOR,
'css': settings.COMPRESS_CSS_COMPRESSOR,
}
def parse(self, parser):
lineno = parser.stream.next().lineno
kindarg = parser.parse_expression()
# Allow kind to be defined as jinja2 name node
if isinstance(kindarg, nodes.Name):
kindarg = nodes.Const(kindarg.name)
args = [kindarg]
if args[0].value not in self.compressors:
raise TemplateSyntaxError('compress kind may be one of: %s' %
(', '.join(self.compressors.keys())),
lineno)
if parser.stream.skip_if('comma'):
modearg = parser.parse_expression()
# Allow mode to be defined as jinja2 name node
if isinstance(modearg, nodes.Name):
modearg = nodes.Const(modearg.name)
args.append(modearg)
else:
args.append(nodes.Const('file'))
body = parser.parse_statements(['name:endcompress'], drop_needle=True)
return nodes.CallBlock(self.call_method('_compress', args), [], [],
body).set_lineno(lineno)
def _compress(self, kind, mode, caller):
mode = mode or OUTPUT_FILE
Compressor = get_class(self.compressors.get(kind),
exception=ImproperlyConfigured)
original_content = caller()
compressor = Compressor(original_content)
# This extension assumes that we won't force compression
forced = False
# Prepare the actual compressor and check cache
cache_key, cache_content = self.render_cached(kind, mode, compressor,
forced)
if cache_content is not None:
return cache_content
# call compressor output method and handle exceptions
try:
rendered_output = compressor.output(mode, forced)
if cache_key:
cache_set(cache_key, rendered_output)
return rendered_output
except Exception, e:
if settings.DEBUG:
raise e
# Or don't do anything in production
return original_content
def render_cached(self, kind, mode, compressor, forced):
"""
If enabled checks the cache for the given compressor's cache key
and return a tuple of cache key and output
"""
if settings.COMPRESS_ENABLED and not forced:
cache_key = get_templatetag_cachekey(compressor, mode, kind)
cache_content = cache_get(cache_key)
return cache_key, cache_content
return None, None