Merge pull request #652 from karyon/various

Refactorings
This commit is contained in:
Mathieu Pillard
2015-09-24 16:27:17 +02:00
6 changed files with 80 additions and 78 deletions

View File

@@ -36,17 +36,19 @@ class Compressor(object):
Base compressor object to be subclassed for content type
depending implementations details.
"""
type = None
def __init__(self, content=None, output_prefix=None, context=None, *args, **kwargs):
def __init__(self, content=None, output_prefix=None,
context=None, filters=None, *args, **kwargs):
self.content = content or "" # rendered contents of {% compress %} tag
self.output_prefix = output_prefix or "compressed"
self.output_dir = settings.COMPRESS_OUTPUT_DIR.strip('/')
self.charset = settings.DEFAULT_CHARSET
self.split_content = []
self.context = context or {}
self.type = output_prefix or ""
self.filters = filters or []
self.extra_context = {}
self.all_mimetypes = dict(settings.COMPRESS_PRECOMPILERS)
self.precompiler_mimetypes = dict(settings.COMPRESS_PRECOMPILERS)
self.finders = staticfiles.finders
self._storage = None
@@ -205,7 +207,7 @@ class Compressor(object):
options = dict(options, filename=value)
value = self.get_filecontent(value, charset)
if self.all_mimetypes:
if self.precompiler_mimetypes:
precompiled, value = self.precompile(value, **options)
if enabled:
@@ -245,34 +247,33 @@ class Compressor(object):
return False, content
attrs = self.parser.elem_attribs(elem)
mimetype = attrs.get("type", None)
if mimetype:
filter_or_command = self.all_mimetypes.get(mimetype)
if filter_or_command is None:
if mimetype not in ("text/css", "text/javascript"):
raise CompressorError("Couldn't find any precompiler in "
"COMPRESS_PRECOMPILERS setting for "
"mimetype '%s'." % mimetype)
else:
mod_name, cls_name = get_mod_func(filter_or_command)
try:
mod = import_module(mod_name)
except (ImportError, TypeError):
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)
except AttributeError:
raise FilterDoesNotExist('Could not find "%s".' %
filter_or_command)
else:
filter = precompiler_class(
content, attrs, filter_type=self.type, charset=charset,
filename=filename)
return True, filter.input(**kwargs)
if mimetype is None:
return False, content
return False, content
filter_or_command = self.precompiler_mimetypes.get(mimetype)
if filter_or_command is None:
if mimetype in ("text/css", "text/javascript"):
return False, content
raise CompressorError("Couldn't find any precompiler in "
"COMPRESS_PRECOMPILERS setting for "
"mimetype '%s'." % mimetype)
mod_name, cls_name = get_mod_func(filter_or_command)
try:
mod = import_module(mod_name)
except (ImportError, TypeError):
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)
except AttributeError:
raise FilterDoesNotExist('Could not find "%s".' % filter_or_command)
filter = precompiler_class(
content, attrs, filter_type=self.type, charset=charset,
filename=filename)
return True, filter.input(**kwargs)
def filter(self, content, method, **kwargs):
for filter_cls in self.cached_filters:

View File

@@ -5,10 +5,8 @@ from compressor.conf import settings
class CssCompressor(Compressor):
def __init__(self, content=None, output_prefix="css", context=None):
super(CssCompressor, self).__init__(content=content,
output_prefix=output_prefix, context=context)
self.filters = list(settings.COMPRESS_CSS_FILTERS)
self.type = output_prefix
filters = list(settings.COMPRESS_CSS_FILTERS)
super(CssCompressor, self).__init__(content, output_prefix, context, filters)
def split_contents(self):
if self.split_content:

View File

@@ -5,9 +5,8 @@ from compressor.base import Compressor, SOURCE_HUNK, SOURCE_FILE
class JsCompressor(Compressor):
def __init__(self, content=None, output_prefix="js", context=None):
super(JsCompressor, self).__init__(content, output_prefix, context)
self.filters = list(settings.COMPRESS_JS_FILTERS)
self.type = output_prefix
filters = list(settings.COMPRESS_JS_FILTERS)
super(JsCompressor, self).__init__(content, output_prefix, context, filters)
def split_contents(self):
if self.split_content:

View File

@@ -40,8 +40,7 @@ class CompressorMixin(object):
def debug_mode(self, context):
if settings.COMPRESS_DEBUG_TOGGLE:
# Only check for the debug parameter
# if a RequestContext was used
# Only check for the debug parameter if a RequestContext was used
request = context.get('request', None)
if request is not None:
return settings.COMPRESS_DEBUG_TOGGLE in request.GET
@@ -57,61 +56,56 @@ class CompressorMixin(object):
return (settings.COMPRESS_ENABLED and
settings.COMPRESS_OFFLINE) or forced
def render_offline(self, context, forced):
def render_offline(self, context):
"""
If enabled and in offline mode, and not forced check the offline cache
and return the result if given
"""
if self.is_offline_compression_enabled(forced) and not forced:
key = get_offline_hexdigest(self.get_original_content(context))
offline_manifest = get_offline_manifest()
if key in offline_manifest:
return offline_manifest[key]
else:
raise OfflineGenerationError('You have offline compression '
'enabled but key "%s" is missing from offline manifest. '
'You may need to run "python manage.py compress".' % key)
key = get_offline_hexdigest(self.get_original_content(context))
offline_manifest = get_offline_manifest()
if key in offline_manifest:
return offline_manifest[key]
else:
raise OfflineGenerationError('You have offline compression '
'enabled but key "%s" is missing from offline manifest. '
'You may need to run "python manage.py compress".' % key)
def render_cached(self, compressor, kind, mode, forced=False):
def render_cached(self, compressor, kind, mode):
"""
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
cache_key = get_templatetag_cachekey(compressor, mode, kind)
cache_content = cache_get(cache_key)
return cache_key, cache_content
def render_compressed(self, context, kind, mode, forced=False):
# See if it has been rendered offline
cached_offline = self.render_offline(context, forced=forced)
if cached_offline:
return cached_offline
if self.is_offline_compression_enabled(forced) and not forced:
return self.render_offline(context)
# Take a shortcut if we really don't have anything to do
if ((not settings.COMPRESS_ENABLED and
not settings.COMPRESS_PRECOMPILERS) and not forced):
if (not settings.COMPRESS_ENABLED and
not settings.COMPRESS_PRECOMPILERS and not forced):
return self.get_original_content(context)
context['compressed'] = {'name': getattr(self, 'name', None)}
compressor = self.get_compressor(context, kind)
# Prepare the actual compressor and check cache
cache_key, cache_content = self.render_cached(compressor, kind, mode, forced=forced)
if cache_content is not None:
return cache_content
# Check cache
cache_key = None
if settings.COMPRESS_ENABLED and not forced:
cache_key, cache_content = self.render_cached(compressor, kind, mode)
if cache_content is not None:
return cache_content
rendered_output = self.render_output(compressor, mode, forced=forced)
rendered_output = compressor.output(mode, forced=forced)
assert isinstance(rendered_output, six.string_types)
if cache_key:
cache_set(cache_key, rendered_output)
return rendered_output
def render_output(self, compressor, mode, forced=False):
return compressor.output(mode, forced=forced)
class CompressorNode(CompressorMixin, template.Node):
@@ -124,14 +118,6 @@ class CompressorNode(CompressorMixin, template.Node):
def get_original_content(self, context):
return self.nodelist.render(context)
def debug_mode(self, context):
if settings.COMPRESS_DEBUG_TOGGLE:
# Only check for the debug parameter
# if a RequestContext was used
request = context.get('request', None)
if request is not None:
return settings.COMPRESS_DEBUG_TOGGLE in request.GET
def render(self, context, forced=False):
# Check if in debug mode

View File

@@ -12,4 +12,4 @@ class FinderTestCase(TestCase):
def test_list_returns_empty_list(self):
finder = CompressorFinder()
self.assertEquals(finder.list([]), [])
self.assertEqual(finder.list([]), [])

View File

@@ -358,6 +358,24 @@ class OfflineGenerationTestCase(OfflineTestCaseMixin, TestCase):
settings.TEMPLATE_LOADERS = old_loaders
class OfflineGenerationEmptyTag(OfflineTestCaseMixin, TestCase):
"""
In case of a compress template tag with no content, an entry
will be added to the manifest with an empty string as value.
This test makes sure there is no recompression happening when
compressor encounters such an emptystring in the manifest.
"""
templates_dir = "basic"
expected_hash = "f5e179b8eca4"
engines = ("django",)
def _test_offline(self, engine):
count, result = CompressCommand().compress(log=self.log, verbosity=self.verbosity, engine=engine)
manifest = get_offline_manifest()
manifest[list(manifest)[0]] = ""
self.assertEqual(self._render_template(engine), "\n")
class OfflineGenerationBlockSuperBaseCompressed(OfflineTestCaseMixin, TestCase):
template_names = ["base.html", "base2.html", "test_compressor_offline.html"]
templates_dir = 'test_block_super_base_compressed'