Merge from upstream.
This commit is contained in:
@@ -1,16 +1,2 @@
|
|||||||
VERSION = (0, 9, 2, "f", 0) # following PEP 386
|
# following PEP 386, versiontools will pick it up
|
||||||
DEV_N = None
|
__version__ = (1, 0, 0, "alpha", 1)
|
||||||
|
|
||||||
|
|
||||||
def get_version():
|
|
||||||
version = "%s.%s" % (VERSION[0], VERSION[1])
|
|
||||||
if VERSION[2]:
|
|
||||||
version = "%s.%s" % (version, VERSION[2])
|
|
||||||
if VERSION[3] != "f":
|
|
||||||
version = "%s%s%s" % (version, VERSION[3], VERSION[4])
|
|
||||||
if DEV_N:
|
|
||||||
version = "%s.dev%s" % (version, DEV_N)
|
|
||||||
return version
|
|
||||||
|
|
||||||
|
|
||||||
__version__ = get_version()
|
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ from __future__ import with_statement
|
|||||||
import os
|
import os
|
||||||
import codecs
|
import codecs
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
|
from django.template import Context
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
|
|
||||||
from compressor.cache import get_hexdigest, get_mtime
|
from compressor.cache import get_hexdigest, get_mtime
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.exceptions import CompressorError, UncompressableFileError
|
from compressor.exceptions import CompressorError, UncompressableFileError
|
||||||
from compressor.filters import CompilerFilter
|
from compressor.filters import CompilerFilter
|
||||||
from compressor.storage import default_storage
|
from compressor.storage import default_storage
|
||||||
@@ -27,13 +29,14 @@ class Compressor(object):
|
|||||||
"""
|
"""
|
||||||
type = None
|
type = None
|
||||||
|
|
||||||
def __init__(self, content=None, output_prefix="compressed", block_name=None):
|
def __init__(self, content=None, output_prefix=None, context=None, *args, **kwargs):
|
||||||
self.content = content or ""
|
self.content = content or ""
|
||||||
self.output_prefix = output_prefix
|
self.output_prefix = output_prefix or "compressed"
|
||||||
self.output_dir = settings.COMPRESS_OUTPUT_DIR.strip('/')
|
self.output_dir = settings.COMPRESS_OUTPUT_DIR.strip('/')
|
||||||
self.charset = settings.DEFAULT_CHARSET
|
self.charset = settings.DEFAULT_CHARSET
|
||||||
self.storage = default_storage
|
self.storage = default_storage
|
||||||
self.split_content = []
|
self.split_content = []
|
||||||
|
self.context = context or {}
|
||||||
self.extra_context = {}
|
self.extra_context = {}
|
||||||
self.all_mimetypes = dict(settings.COMPRESS_PRECOMPILERS)
|
self.all_mimetypes = dict(settings.COMPRESS_PRECOMPILERS)
|
||||||
self.finders = staticfiles.finders
|
self.finders = staticfiles.finders
|
||||||
@@ -86,6 +89,11 @@ class Compressor(object):
|
|||||||
except IOError, e:
|
except IOError, e:
|
||||||
raise UncompressableFileError("IOError while processing "
|
raise UncompressableFileError("IOError while processing "
|
||||||
"'%s': %s" % (filename, e))
|
"'%s': %s" % (filename, e))
|
||||||
|
except UnicodeDecodeError, e:
|
||||||
|
raise UncompressableFileError("UnicodeDecodeError while "
|
||||||
|
"processing '%s' with "
|
||||||
|
"charset %s: %s" %
|
||||||
|
(filename, charset, e))
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def parser(self):
|
def parser(self):
|
||||||
@@ -250,7 +258,10 @@ class Compressor(object):
|
|||||||
"""
|
"""
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
context.update(self.extra_context)
|
final_context = Context()
|
||||||
post_compress.send(sender='django-compressor', name=self.block_name, type=self.type, mode=mode, context=context)
|
final_context.update(context)
|
||||||
return render_to_string(
|
final_context.update(self.context)
|
||||||
"compressor/%s_%s.html" % (self.type, mode), context)
|
final_context.update(self.extra_context)
|
||||||
|
post_compress.send(sender='django-compressor', name=self.block_name, type=self.type, mode=mode, context=final_context)
|
||||||
|
return render_to_string("compressor/%s_%s.html" %
|
||||||
|
(self.type, mode), final_context)
|
||||||
|
|||||||
@@ -2,14 +2,17 @@ import os
|
|||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.cache import get_cache
|
from django.core.cache import get_cache
|
||||||
from django.utils.encoding import smart_str
|
from django.utils.encoding import smart_str
|
||||||
|
from django.utils.functional import SimpleLazyObject
|
||||||
from django.utils.hashcompat import md5_constructor
|
from django.utils.hashcompat import md5_constructor
|
||||||
from django.utils.importlib import import_module
|
from django.utils.importlib import import_module
|
||||||
|
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.utils import get_mod_func
|
from compressor.utils import get_mod_func
|
||||||
|
|
||||||
|
_cachekey_func = None
|
||||||
|
|
||||||
|
|
||||||
def get_hexdigest(plaintext, length=None):
|
def get_hexdigest(plaintext, length=None):
|
||||||
digest = md5_constructor(smart_str(plaintext)).hexdigest()
|
digest = md5_constructor(smart_str(plaintext)).hexdigest()
|
||||||
@@ -17,18 +20,26 @@ def get_hexdigest(plaintext, length=None):
|
|||||||
return digest[:length]
|
return digest[:length]
|
||||||
return digest
|
return digest
|
||||||
|
|
||||||
|
|
||||||
def simple_cachekey(key):
|
def simple_cachekey(key):
|
||||||
return 'django_compressor.%s' % smart_str(key)
|
return 'django_compressor.%s' % smart_str(key)
|
||||||
|
|
||||||
|
|
||||||
def socket_cachekey(key):
|
def socket_cachekey(key):
|
||||||
return "django_compressor.%s.%s" % (socket.gethostname(), smart_str(key))
|
return "django_compressor.%s.%s" % (socket.gethostname(), smart_str(key))
|
||||||
|
|
||||||
try:
|
|
||||||
mod_name, func_name = get_mod_func(settings.COMPRESS_CACHE_KEY_FUNCTION)
|
def get_cachekey(*args, **kwargs):
|
||||||
get_cachekey = getattr(import_module(mod_name), func_name)
|
global _cachekey_func
|
||||||
except (AttributeError, ImportError), e:
|
if _cachekey_func is None:
|
||||||
raise ImportError("Couldn't import cache key function %s: %s" %
|
try:
|
||||||
(settings.COMPRESS_CACHE_KEY_FUNCTION, e))
|
mod_name, func_name = get_mod_func(settings.COMPRESS_CACHE_KEY_FUNCTION)
|
||||||
|
_cachekey_func = getattr(import_module(mod_name), func_name)
|
||||||
|
except (AttributeError, ImportError), e:
|
||||||
|
raise ImportError("Couldn't import cache key function %s: %s" %
|
||||||
|
(settings.COMPRESS_CACHE_KEY_FUNCTION, e))
|
||||||
|
return _cachekey_func(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_mtime_cachekey(filename):
|
def get_mtime_cachekey(filename):
|
||||||
return get_cachekey("mtime.%s" % get_hexdigest(filename))
|
return get_cachekey("mtime.%s" % get_hexdigest(filename))
|
||||||
@@ -78,12 +89,13 @@ def cache_get(key):
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
def cache_set(key, val, refreshed=False,
|
def cache_set(key, val, refreshed=False, timeout=None):
|
||||||
timeout=settings.COMPRESS_REBUILD_TIMEOUT):
|
if timeout is None:
|
||||||
|
timeout = settings.COMPRESS_REBUILD_TIMEOUT
|
||||||
refresh_time = timeout + time.time()
|
refresh_time = timeout + time.time()
|
||||||
real_timeout = timeout + settings.COMPRESS_MINT_DELAY
|
real_timeout = timeout + settings.COMPRESS_MINT_DELAY
|
||||||
packed_val = (val, refresh_time, refreshed)
|
packed_val = (val, refresh_time, refreshed)
|
||||||
return cache.set(key, packed_val, real_timeout)
|
return cache.set(key, packed_val, real_timeout)
|
||||||
|
|
||||||
|
|
||||||
cache = get_cache(settings.COMPRESS_CACHE_BACKEND)
|
cache = SimpleLazyObject(lambda: get_cache(settings.COMPRESS_CACHE_BACKEND))
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from compressor.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.base import Compressor, SOURCE_HUNK, SOURCE_FILE
|
from compressor.base import Compressor, SOURCE_HUNK, SOURCE_FILE
|
||||||
from compressor.exceptions import UncompressableFileError
|
from compressor.exceptions import UncompressableFileError
|
||||||
|
|
||||||
@@ -7,8 +8,9 @@ class CssCompressor(Compressor):
|
|||||||
template_name = "compressor/css.html"
|
template_name = "compressor/css.html"
|
||||||
template_name_inline = "compressor/css_inline.html"
|
template_name_inline = "compressor/css_inline.html"
|
||||||
|
|
||||||
def __init__(self, content=None, output_prefix="css", block_name=None):
|
def __init__(self, content=None, output_prefix="css", context=None):
|
||||||
super(CssCompressor, self).__init__(content, output_prefix, block_name)
|
super(CssCompressor, self).__init__(content=content,
|
||||||
|
output_prefix=output_prefix, context=context)
|
||||||
self.filters = list(settings.COMPRESS_CSS_FILTERS)
|
self.filters = list(settings.COMPRESS_CSS_FILTERS)
|
||||||
self.type = output_prefix
|
self.type = output_prefix
|
||||||
|
|
||||||
@@ -34,7 +36,8 @@ class CssCompressor(Compressor):
|
|||||||
if self.media_nodes and self.media_nodes[-1][0] == media:
|
if self.media_nodes and self.media_nodes[-1][0] == media:
|
||||||
self.media_nodes[-1][1].split_content.append(data)
|
self.media_nodes[-1][1].split_content.append(data)
|
||||||
else:
|
else:
|
||||||
node = CssCompressor(self.parser.elem_str(elem), block_name=self.block_name)
|
node = CssCompressor(content=self.parser.elem_str(elem),
|
||||||
|
context=self.context)
|
||||||
node.split_content.append(data)
|
node.split_content.append(data)
|
||||||
self.media_nodes.append((media, node))
|
self.media_nodes.append((media, node))
|
||||||
return self.split_content
|
return self.split_content
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.files.temp import NamedTemporaryFile
|
from django.core.files.temp import NamedTemporaryFile
|
||||||
from django.utils.importlib import import_module
|
from django.utils.importlib import import_module
|
||||||
|
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.exceptions import FilterError
|
from compressor.exceptions import FilterError
|
||||||
from compressor.utils import get_mod_func
|
from compressor.utils import get_mod_func
|
||||||
from compressor.utils.stringformat import FormattableString as fstr
|
from compressor.utils.stringformat import FormattableString as fstr
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from compressor.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.filters import CompilerFilter
|
from compressor.filters import CompilerFilter
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import os
|
|||||||
import re
|
import re
|
||||||
import posixpath
|
import posixpath
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.cache import get_hexdigest, get_hashed_mtime
|
from compressor.cache import get_hexdigest, get_hashed_mtime
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.filters import FilterBase
|
from compressor.filters import FilterBase
|
||||||
from compressor.utils import staticfiles
|
from compressor.utils import staticfiles
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from compressor.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.filters import CompilerFilter
|
from compressor.filters import CompilerFilter
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import re
|
|||||||
import mimetypes
|
import mimetypes
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
|
|
||||||
from compressor.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.filters import FilterBase
|
from compressor.filters import FilterBase
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from compressor.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.filters import CompilerFilter
|
from compressor.filters import CompilerFilter
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from compressor.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.base import Compressor, SOURCE_HUNK, SOURCE_FILE
|
from compressor.base import Compressor, SOURCE_HUNK, SOURCE_FILE
|
||||||
from compressor.exceptions import UncompressableFileError
|
from compressor.exceptions import UncompressableFileError
|
||||||
|
|
||||||
@@ -7,8 +8,8 @@ class JsCompressor(Compressor):
|
|||||||
template_name = "compressor/js.html"
|
template_name = "compressor/js.html"
|
||||||
template_name_inline = "compressor/js_inline.html"
|
template_name_inline = "compressor/js_inline.html"
|
||||||
|
|
||||||
def __init__(self, content=None, output_prefix="js", block_name=None):
|
def __init__(self, content=None, output_prefix="js", context=None):
|
||||||
super(JsCompressor, self).__init__(content, output_prefix, block_name)
|
super(JsCompressor, self).__init__(content, output_prefix, context)
|
||||||
self.filters = list(settings.COMPRESS_JS_FILTERS)
|
self.filters = list(settings.COMPRESS_JS_FILTERS)
|
||||||
self.type = output_prefix
|
self.type = output_prefix
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.management.base import NoArgsCommand, CommandError
|
from django.core.management.base import NoArgsCommand, CommandError
|
||||||
from django.template import Context, Template, TemplateDoesNotExist, TemplateSyntaxError
|
from django.template import Context, Template, TemplateDoesNotExist, TemplateSyntaxError
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
@@ -22,7 +23,6 @@ except ImportError:
|
|||||||
CachedLoader = None
|
CachedLoader = None
|
||||||
|
|
||||||
from compressor.cache import cache, get_offline_cachekey
|
from compressor.cache import cache, get_offline_cachekey
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.exceptions import OfflineGenerationError
|
from compressor.exceptions import OfflineGenerationError
|
||||||
from compressor.templatetags.compress import CompressorNode
|
from compressor.templatetags.compress import CompressorNode
|
||||||
from compressor.utils import walk, any
|
from compressor.utils import walk, any
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import fnmatch
|
|||||||
import os
|
import os
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.management.base import NoArgsCommand, CommandError
|
from django.core.management.base import NoArgsCommand, CommandError
|
||||||
|
|
||||||
from compressor.cache import cache, get_mtime, get_mtime_cachekey
|
from compressor.cache import cache, get_mtime, get_mtime_cachekey
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.utils import walk
|
from compressor.utils import walk
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
from django import VERSION as DJANGO_VERSION
|
from django import VERSION as DJANGO_VERSION
|
||||||
from django.conf import settings as global_settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
from compressor.utils.settings import AppSettings
|
from appconf import AppConf
|
||||||
|
|
||||||
class CompressorSettings(AppSettings):
|
|
||||||
|
class CompressorConf(AppConf):
|
||||||
# Main switch
|
# Main switch
|
||||||
ENABLED = False
|
ENABLED = False
|
||||||
# Allows changing verbosity from the settings.
|
# Allows changing verbosity from the settings.
|
||||||
@@ -60,14 +61,17 @@ class CompressorSettings(AppSettings):
|
|||||||
# The context to be used when compressing the files "offline"
|
# The context to be used when compressing the files "offline"
|
||||||
OFFLINE_CONTEXT = {}
|
OFFLINE_CONTEXT = {}
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
prefix = 'compress'
|
||||||
|
|
||||||
def configure_enabled(self, value):
|
def configure_enabled(self, value):
|
||||||
return value or not global_settings.DEBUG
|
return value or not settings.DEBUG
|
||||||
|
|
||||||
def configure_root(self, value):
|
def configure_root(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
value = getattr(global_settings, 'STATIC_ROOT', None)
|
value = getattr(settings, 'STATIC_ROOT', None)
|
||||||
if not value:
|
if not value:
|
||||||
value = global_settings.MEDIA_ROOT
|
value = settings.MEDIA_ROOT
|
||||||
if not value:
|
if not value:
|
||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
"The COMPRESS_ROOT setting must be set.")
|
"The COMPRESS_ROOT setting must be set.")
|
||||||
@@ -76,9 +80,9 @@ class CompressorSettings(AppSettings):
|
|||||||
def configure_url(self, value):
|
def configure_url(self, value):
|
||||||
# Uses Django 1.3's STATIC_URL by default or falls back to MEDIA_URL
|
# Uses Django 1.3's STATIC_URL by default or falls back to MEDIA_URL
|
||||||
if value is None:
|
if value is None:
|
||||||
value = getattr(global_settings, "STATIC_URL", None)
|
value = getattr(settings, "STATIC_URL", None)
|
||||||
if not value:
|
if not value:
|
||||||
value = global_settings.MEDIA_URL
|
value = settings.MEDIA_URL
|
||||||
if not value.endswith("/"):
|
if not value.endswith("/"):
|
||||||
raise ImproperlyConfigured("The URL settings (e.g. COMPRESS_URL) "
|
raise ImproperlyConfigured("The URL settings (e.g. COMPRESS_URL) "
|
||||||
"must have a trailing slash.")
|
"must have a trailing slash.")
|
||||||
@@ -87,11 +91,11 @@ class CompressorSettings(AppSettings):
|
|||||||
def configure_cache_backend(self, value):
|
def configure_cache_backend(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
# If we are on Django 1.3 AND using the new CACHES setting...
|
# If we are on Django 1.3 AND using the new CACHES setting...
|
||||||
if DJANGO_VERSION[:2] >= (1, 3) and hasattr(global_settings, "CACHES"):
|
if DJANGO_VERSION[:2] >= (1, 3) and hasattr(settings, "CACHES"):
|
||||||
value = "default"
|
value = "default"
|
||||||
else:
|
else:
|
||||||
# falling back to the old CACHE_BACKEND setting
|
# falling back to the old CACHE_BACKEND setting
|
||||||
value = getattr(global_settings, "CACHE_BACKEND", None)
|
value = getattr(settings, "CACHE_BACKEND", None)
|
||||||
if not value:
|
if not value:
|
||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
"Please specify a cache backend in your settings.")
|
"Please specify a cache backend in your settings.")
|
||||||
@@ -100,11 +104,11 @@ class CompressorSettings(AppSettings):
|
|||||||
def configure_offline_context(self, value):
|
def configure_offline_context(self, value):
|
||||||
if not value:
|
if not value:
|
||||||
value = {
|
value = {
|
||||||
"MEDIA_URL": global_settings.MEDIA_URL,
|
"MEDIA_URL": settings.MEDIA_URL,
|
||||||
}
|
}
|
||||||
# Adds the 1.3 STATIC_URL setting to the context if available
|
# Adds the 1.3 STATIC_URL setting to the context if available
|
||||||
if getattr(global_settings, "STATIC_URL", None):
|
if getattr(settings, "STATIC_URL", None):
|
||||||
value["STATIC_URL"] = global_settings.STATIC_URL
|
value["STATIC_URL"] = settings.STATIC_URL
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def configure_precompilers(self, value):
|
def configure_precompilers(self, value):
|
||||||
@@ -112,5 +116,3 @@ class CompressorSettings(AppSettings):
|
|||||||
raise ImproperlyConfigured("The COMPRESS_PRECOMPILERS setting "
|
raise ImproperlyConfigured("The COMPRESS_PRECOMPILERS setting "
|
||||||
"must be a list or tuple. Check for missing commas.")
|
"must be a list or tuple. Check for missing commas.")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
settings = CompressorSettings(prefix="COMPRESS")
|
|
||||||
@@ -2,11 +2,10 @@ import gzip
|
|||||||
from os import path
|
from os import path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.files.storage import FileSystemStorage, get_storage_class
|
from django.core.files.storage import FileSystemStorage, get_storage_class
|
||||||
from django.utils.functional import LazyObject
|
from django.utils.functional import LazyObject
|
||||||
|
|
||||||
from compressor.conf import settings
|
|
||||||
|
|
||||||
|
|
||||||
class CompressorFileStorage(FileSystemStorage):
|
class CompressorFileStorage(FileSystemStorage):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<link rel="stylesheet" href="{{ url }}" type="text/css"{% if media %} media="{{ media }}"{% endif %} />
|
<link rel="stylesheet" href="{{ url }}" type="text/css"{% if media %} media="{{ media }}"{% endif %} />
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
from django import template
|
from django import template
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
from compressor.cache import (cache, cache_get, cache_set,
|
from compressor.cache import (cache, cache_get, cache_set,
|
||||||
get_offline_cachekey, get_templatetag_cachekey)
|
get_offline_cachekey, get_templatetag_cachekey)
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.utils import get_class
|
from compressor.utils import get_class
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
@@ -11,10 +11,6 @@ register = template.Library()
|
|||||||
OUTPUT_FILE = 'file'
|
OUTPUT_FILE = 'file'
|
||||||
OUTPUT_INLINE = 'inline'
|
OUTPUT_INLINE = 'inline'
|
||||||
OUTPUT_MODES = (OUTPUT_FILE, OUTPUT_INLINE)
|
OUTPUT_MODES = (OUTPUT_FILE, OUTPUT_INLINE)
|
||||||
COMPRESSORS = {
|
|
||||||
"css": settings.COMPRESS_CSS_COMPRESSOR,
|
|
||||||
"js": settings.COMPRESS_JS_COMPRESSOR,
|
|
||||||
}
|
|
||||||
|
|
||||||
class CompressorNode(template.Node):
|
class CompressorNode(template.Node):
|
||||||
|
|
||||||
@@ -22,9 +18,17 @@ class CompressorNode(template.Node):
|
|||||||
self.nodelist = nodelist
|
self.nodelist = nodelist
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.name = name
|
|
||||||
self.compressor_cls = get_class(
|
def compressor_cls(self, *args, **kwargs):
|
||||||
COMPRESSORS.get(self.kind), exception=ImproperlyConfigured)
|
compressors = {
|
||||||
|
"css": settings.COMPRESS_CSS_COMPRESSOR,
|
||||||
|
"js": settings.COMPRESS_JS_COMPRESSOR,
|
||||||
|
}
|
||||||
|
if self.kind not in compressors.keys():
|
||||||
|
raise template.TemplateSyntaxError(
|
||||||
|
"The compress tag's argument must be 'js' or 'css'.")
|
||||||
|
return get_class(compressors.get(self.kind),
|
||||||
|
exception=ImproperlyConfigured)(*args, **kwargs)
|
||||||
|
|
||||||
def debug_mode(self, context):
|
def debug_mode(self, context):
|
||||||
if settings.COMPRESS_DEBUG_TOGGLE:
|
if settings.COMPRESS_DEBUG_TOGGLE:
|
||||||
@@ -66,7 +70,8 @@ class CompressorNode(template.Node):
|
|||||||
return cached_offline
|
return cached_offline
|
||||||
|
|
||||||
# 3. Prepare the actual compressor and check cache
|
# 3. Prepare the actual compressor and check cache
|
||||||
compressor = self.compressor_cls(self.nodelist.render(context), block_name=self.name)
|
compressor = self.compressor_cls(content=self.nodelist.render(context),
|
||||||
|
context=context)
|
||||||
cache_key, cache_content = self.render_cached(compressor, forced)
|
cache_key, cache_content = self.render_cached(compressor, forced)
|
||||||
if cache_content is not None:
|
if cache_content is not None:
|
||||||
return cache_content
|
return cache_content
|
||||||
@@ -127,9 +132,6 @@ def compress(parser, token):
|
|||||||
"%r tag requires either one or two arguments." % args[0])
|
"%r tag requires either one or two arguments." % args[0])
|
||||||
|
|
||||||
kind = args[1]
|
kind = args[1]
|
||||||
if not kind in COMPRESSORS.keys():
|
|
||||||
raise template.TemplateSyntaxError(
|
|
||||||
"%r's argument must be 'js' or 'css'." % args[0])
|
|
||||||
|
|
||||||
if len(args) == 3:
|
if len(args) == 3:
|
||||||
mode = args[2]
|
mode = args[2]
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
from inspect import getmembers
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
class AppSettings(object):
|
|
||||||
"""
|
|
||||||
An app setting object to be used for handling app setting defaults
|
|
||||||
gracefully and providing a nice API for them. Say you have an app
|
|
||||||
called ``myapp`` and want to define a few defaults, and refer to the
|
|
||||||
defaults easily in the apps code. Add a ``settings.py`` to your app::
|
|
||||||
|
|
||||||
from path.to.utils import AppSettings
|
|
||||||
|
|
||||||
class MyAppSettings(AppSettings):
|
|
||||||
SETTING_1 = "one"
|
|
||||||
SETTING_2 = (
|
|
||||||
"two",
|
|
||||||
)
|
|
||||||
|
|
||||||
Then initialize the setting with the correct prefix in the location of
|
|
||||||
of your choice, e.g. ``conf.py`` of the app module::
|
|
||||||
|
|
||||||
settings = MyAppSettings(prefix="MYAPP")
|
|
||||||
|
|
||||||
The ``MyAppSettings`` instance will automatically look at Django's
|
|
||||||
global setting to determine each of the settings and respect the
|
|
||||||
provided ``prefix``. E.g. adding this to your site's ``settings.py``
|
|
||||||
will set the ``SETTING_1`` setting accordingly::
|
|
||||||
|
|
||||||
MYAPP_SETTING_1 = "uno"
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
Instead of using ``from django.conf import settings`` as you would
|
|
||||||
usually do, you can switch to using your apps own settings module
|
|
||||||
to access the app settings::
|
|
||||||
|
|
||||||
from myapp.conf import settings
|
|
||||||
|
|
||||||
print myapp_settings.MYAPP_SETTING_1
|
|
||||||
|
|
||||||
``AppSettings`` instances also work as pass-throughs for other
|
|
||||||
global settings that aren't related to the app. For example the
|
|
||||||
following code is perfectly valid::
|
|
||||||
|
|
||||||
from myapp.conf import settings
|
|
||||||
|
|
||||||
if "myapp" in settings.INSTALLED_APPS:
|
|
||||||
print "yay, myapp is installed!"
|
|
||||||
|
|
||||||
Custom handling
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Each of the settings can be individually configured with callbacks.
|
|
||||||
For example, in case a value of a setting depends on other settings
|
|
||||||
or other dependencies. The following example sets one setting to a
|
|
||||||
different value depending on a global setting::
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
class MyCustomAppSettings(AppSettings):
|
|
||||||
ENABLED = True
|
|
||||||
|
|
||||||
def configure_enabled(self, value):
|
|
||||||
return value and not self.DEBUG
|
|
||||||
|
|
||||||
custom_settings = MyCustomAppSettings("MYAPP")
|
|
||||||
|
|
||||||
The value of ``custom_settings.MYAPP_ENABLED`` will vary depending on the
|
|
||||||
value of the global ``DEBUG`` setting.
|
|
||||||
|
|
||||||
Each of the app settings can be customized by providing
|
|
||||||
a method ``configure_<lower_setting_name>`` that takes the default
|
|
||||||
value as defined in the class attributes as the only parameter.
|
|
||||||
The method needs to return the value to be use for the setting in
|
|
||||||
question.
|
|
||||||
"""
|
|
||||||
def __dir__(self):
|
|
||||||
return sorted(list(set(self.__dict__.keys() + dir(settings))))
|
|
||||||
|
|
||||||
__members__ = lambda self: self.__dir__()
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
if name.startswith(self._prefix):
|
|
||||||
raise AttributeError("%r object has no attribute %r" %
|
|
||||||
(self.__class__.__name__, name))
|
|
||||||
return getattr(settings, name)
|
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
|
||||||
super(AppSettings, self).__setattr__(name, value)
|
|
||||||
if name in dir(settings):
|
|
||||||
setattr(settings, name, value)
|
|
||||||
|
|
||||||
def __init__(self, prefix):
|
|
||||||
super(AppSettings, self).__setattr__('_prefix', prefix)
|
|
||||||
for name, value in filter(self.issetting, getmembers(self.__class__)):
|
|
||||||
prefixed_name = "%s_%s" % (prefix.upper(), name.upper())
|
|
||||||
value = getattr(settings, prefixed_name, value)
|
|
||||||
callback = getattr(self, "configure_%s" % name.lower(), None)
|
|
||||||
if callable(callback):
|
|
||||||
value = callback(value)
|
|
||||||
delattr(self.__class__, name)
|
|
||||||
setattr(self, prefixed_name, value)
|
|
||||||
|
|
||||||
def issetting(self, (name, value)):
|
|
||||||
return name == name.upper()
|
|
||||||
|
|
||||||
@@ -40,8 +40,14 @@ HEAD
|
|||||||
- Added new CallbackOutputFilter to ease the implementation of Python-based
|
- Added new CallbackOutputFilter to ease the implementation of Python-based
|
||||||
callback filters that only need to pass the content to a callable.
|
callback filters that only need to pass the content to a callable.
|
||||||
|
|
||||||
|
- Make use of `django-appconf`_ for settings handling and `versiontools`_
|
||||||
|
for versions.
|
||||||
|
|
||||||
|
- Uses the current context when rendering the render templates.
|
||||||
|
|
||||||
.. _`Slim It`: http://slimit.org/
|
.. _`Slim It`: http://slimit.org/
|
||||||
|
.. _`django-appconf`: http://django-appconf.rtfd.org/
|
||||||
|
.. _`versiontools`: http://pypi.python.org/pypi/versiontools
|
||||||
|
|
||||||
0.9.2
|
0.9.2
|
||||||
-----
|
-----
|
||||||
|
|||||||
23
setup.py
23
setup.py
@@ -1,11 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import codecs
|
||||||
from fnmatch import fnmatchcase
|
from fnmatch import fnmatchcase
|
||||||
from distutils.util import convert_path
|
from distutils.util import convert_path
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
def read(fname):
|
def read(fname):
|
||||||
return open(os.path.join(os.path.dirname(__file__), fname)).read()
|
return codecs.open(os.path.join(os.path.dirname(__file__), fname)).read()
|
||||||
|
|
||||||
# Provided as an attribute, so you can append to these instead
|
# Provided as an attribute, so you can append to these instead
|
||||||
# of replicating them:
|
# of replicating them:
|
||||||
@@ -97,16 +98,13 @@ def find_package_data(
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
README = read('README.rst')
|
|
||||||
VERSION = __import__("compressor").__version__
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = "django_compressor",
|
name = "django_compressor",
|
||||||
version = VERSION,
|
version = ":versiontools:compressor:",
|
||||||
url = 'http://django_compressor.readthedocs.org/',
|
url = 'http://django_compressor.readthedocs.org/',
|
||||||
license = 'BSD',
|
license = 'MIT',
|
||||||
description = "Compresses linked and inline JavaScript or CSS into single cached files.",
|
description = "Compresses linked and inline JavaScript or CSS into single cached files.",
|
||||||
long_description = README,
|
long_description = read('README.rst'),
|
||||||
author = 'Jannis Leidel',
|
author = 'Jannis Leidel',
|
||||||
author_email = 'jannis@leidel.info',
|
author_email = 'jannis@leidel.info',
|
||||||
packages = find_packages(exclude=['tests', 'tests.*']),
|
packages = find_packages(exclude=['tests', 'tests.*']),
|
||||||
@@ -115,10 +113,19 @@ setup(
|
|||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
'Framework :: Django',
|
'Framework :: Django',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'License :: OSI Approved :: BSD License',
|
'License :: OSI Approved :: MIT License',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
|
'Programming Language :: Python :: 2.5',
|
||||||
|
'Programming Language :: Python :: 2.6',
|
||||||
|
'Programming Language :: Python :: 2.7',
|
||||||
'Topic :: Internet :: WWW/HTTP',
|
'Topic :: Internet :: WWW/HTTP',
|
||||||
],
|
],
|
||||||
zip_safe = False,
|
zip_safe = False,
|
||||||
|
install_requires=[
|
||||||
|
'django-appconf >= 0.4',
|
||||||
|
],
|
||||||
|
setup_requires=[
|
||||||
|
'versiontools >= 1.6',
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
24
tests/settings.py
Normal file
24
tests/settings.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
COMPRESS_CACHE_BACKEND = 'locmem://'
|
||||||
|
|
||||||
|
DATABASE_ENGINE = 'sqlite3'
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sites',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.admin',
|
||||||
|
'compressor',
|
||||||
|
'tests',
|
||||||
|
]
|
||||||
|
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
|
||||||
|
MEDIA_ROOT = os.path.join(TEST_DIR, 'media')
|
||||||
|
|
||||||
|
TEMPLATE_DIRS = (
|
||||||
|
os.path.join(TEST_DIR, 'templates'),
|
||||||
|
)
|
||||||
@@ -4,12 +4,11 @@ import re
|
|||||||
|
|
||||||
from BeautifulSoup import BeautifulSoup
|
from BeautifulSoup import BeautifulSoup
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.cache.backends import locmem
|
from django.core.cache.backends import locmem
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from compressor.base import SOURCE_HUNK, SOURCE_FILE
|
from compressor.base import SOURCE_HUNK, SOURCE_FILE
|
||||||
from compressor.cache import get_hexdigest
|
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.css import CssCompressor
|
from compressor.css import CssCompressor
|
||||||
from compressor.js import JsCompressor
|
from compressor.js import JsCompressor
|
||||||
|
|
||||||
@@ -22,6 +21,7 @@ def css_tag(href, **kwargs):
|
|||||||
|
|
||||||
test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
|
||||||
|
|
||||||
class CompressorTestCase(TestCase):
|
class CompressorTestCase(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -81,7 +81,7 @@ class CompressorTestCase(TestCase):
|
|||||||
def test_js_split(self):
|
def test_js_split(self):
|
||||||
out = [
|
out = [
|
||||||
(SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), u'js/one.js', '<script src="/media/js/one.js" type="text/javascript"></script>'),
|
(SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), u'js/one.js', '<script src="/media/js/one.js" type="text/javascript"></script>'),
|
||||||
(SOURCE_HUNK, u'obj.value = "value";', None, '<script type="text/javascript">obj.value = "value";</script>')
|
(SOURCE_HUNK, u'obj.value = "value";', None, '<script type="text/javascript">obj.value = "value";</script>'),
|
||||||
]
|
]
|
||||||
split = self.js_node.split_contents()
|
split = self.js_node.split_contents()
|
||||||
split = [(x[0], x[1], x[2], self.js_node.parser.elem_str(x[3])) for x in split]
|
split = [(x[0], x[1], x[2], self.js_node.parser.elem_str(x[3])) for x in split]
|
||||||
@@ -127,7 +127,6 @@ class CompressorTestCase(TestCase):
|
|||||||
settings.COMPRESS_OUTPUT_DIR = old_output_dir
|
settings.COMPRESS_OUTPUT_DIR = old_output_dir
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CssMediaTestCase(TestCase):
|
class CssMediaTestCase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.css = """\
|
self.css = """\
|
||||||
@@ -151,8 +150,6 @@ class CssMediaTestCase(TestCase):
|
|||||||
self.assertEqual(media, [l.get('media', None) for l in links])
|
self.assertEqual(media, [l.get('media', None) for l in links])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class VerboseTestCase(CompressorTestCase):
|
class VerboseTestCase(CompressorTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -165,5 +162,3 @@ class CacheBackendTestCase(CompressorTestCase):
|
|||||||
def test_correct_backend(self):
|
def test_correct_backend(self):
|
||||||
from compressor.cache import cache
|
from compressor.cache import cache
|
||||||
self.assertEqual(cache.__class__, locmem.CacheClass)
|
self.assertEqual(cache.__class__, locmem.CacheClass)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
from unittest2 import skipIf
|
from unittest2 import skipIf
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from compressor.cache import get_hashed_mtime
|
from compressor.cache import get_hashed_mtime
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.css import CssCompressor
|
from compressor.css import CssCompressor
|
||||||
from compressor.utils import find_command
|
from compressor.utils import find_command
|
||||||
from compressor.filters.base import CompilerFilter
|
from compressor.filters.base import CompilerFilter
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.template import Template, Context
|
from django.template import Template, Context
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from compressor.conf import settings
|
|
||||||
from compressor.management.commands.compress import Command as CompressCommand
|
from compressor.management.commands.compress import Command as CompressCommand
|
||||||
|
|
||||||
from .base import test_dir, css_tag
|
from .base import test_dir, css_tag
|
||||||
@@ -30,11 +30,11 @@ class OfflineGenerationTestCase(TestCase):
|
|||||||
count, result = CompressCommand().compress()
|
count, result = CompressCommand().compress()
|
||||||
self.assertEqual(5, count)
|
self.assertEqual(5, count)
|
||||||
self.assertEqual([
|
self.assertEqual([
|
||||||
css_tag('/media/CACHE/css/cd579b7deb7d.css')+'\n',
|
css_tag('/media/CACHE/css/cd579b7deb7d.css'),
|
||||||
u'<script type="text/javascript" src="/media/CACHE/js/0a2bb9a287c0.js"></script>',
|
u'<script type="text/javascript" src="/media/CACHE/js/0a2bb9a287c0.js"></script>',
|
||||||
u'<script type="text/javascript" src="/media/CACHE/js/fb1736ad48b7.js"></script>',
|
u'<script type="text/javascript" src="/media/CACHE/js/fb1736ad48b7.js"></script>',
|
||||||
u'<script type="text/javascript" src="/media/CACHE/js/770a7311729e.js"></script>',
|
u'<script type="text/javascript" src="/media/CACHE/js/770a7311729e.js"></script>',
|
||||||
u'<link rel="stylesheet" href="/media/CACHE/css/67ed6aff7f7b.css" type="text/css" />\n',
|
u'<link rel="stylesheet" href="/media/CACHE/css/67ed6aff7f7b.css" type="text/css" />',
|
||||||
], result)
|
], result)
|
||||||
# Template rendering should use the cache. FIXME: how to make sure of it ? Should we test the cache
|
# Template rendering should use the cache. FIXME: how to make sure of it ? Should we test the cache
|
||||||
# key<->values ourselves?
|
# key<->values ourselves?
|
||||||
@@ -49,11 +49,11 @@ class OfflineGenerationTestCase(TestCase):
|
|||||||
count, result = CompressCommand().compress()
|
count, result = CompressCommand().compress()
|
||||||
self.assertEqual(5, count)
|
self.assertEqual(5, count)
|
||||||
self.assertEqual([
|
self.assertEqual([
|
||||||
css_tag('/media/CACHE/css/ee62fbfd116a.css')+'\n',
|
css_tag('/media/CACHE/css/ee62fbfd116a.css'),
|
||||||
u'<script type="text/javascript" src="/media/CACHE/js/0a2bb9a287c0.js"></script>',
|
u'<script type="text/javascript" src="/media/CACHE/js/0a2bb9a287c0.js"></script>',
|
||||||
u'<script type="text/javascript" src="/media/CACHE/js/fb1736ad48b7.js"></script>',
|
u'<script type="text/javascript" src="/media/CACHE/js/fb1736ad48b7.js"></script>',
|
||||||
u'<script type="text/javascript" src="/media/CACHE/js/770a7311729e.js"></script>',
|
u'<script type="text/javascript" src="/media/CACHE/js/770a7311729e.js"></script>',
|
||||||
u'<link rel="stylesheet" href="/media/CACHE/css/73e015f740c6.css" type="text/css" />\n',
|
u'<link rel="stylesheet" href="/media/CACHE/css/73e015f740c6.css" type="text/css" />',
|
||||||
], result)
|
], result)
|
||||||
# Template rendering should use the cache. FIXME: how to make sure of it ? Should we test the cache
|
# Template rendering should use the cache. FIXME: how to make sure of it ? Should we test the cache
|
||||||
# key<->values ourselves?
|
# key<->values ourselves?
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ from __future__ import with_statement
|
|||||||
import os
|
import os
|
||||||
from unittest2 import skipIf
|
from unittest2 import skipIf
|
||||||
|
|
||||||
from BeautifulSoup import BeautifulSoup
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import lxml
|
import lxml
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -20,7 +18,8 @@ except ImportError:
|
|||||||
BeautifulSoup = None
|
BeautifulSoup = None
|
||||||
|
|
||||||
|
|
||||||
from compressor.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from compressor.base import SOURCE_HUNK, SOURCE_FILE
|
from compressor.base import SOURCE_HUNK, SOURCE_FILE
|
||||||
|
|
||||||
from .base import CompressorTestCase
|
from .base import CompressorTestCase
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.files.storage import get_storage_class
|
from django.core.files.storage import get_storage_class
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from compressor import base
|
from compressor import base
|
||||||
from compressor.conf import settings
|
|
||||||
|
|
||||||
from .base import css_tag
|
from .base import css_tag
|
||||||
from .templatetags import render
|
from .templatetags import render
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.template import Template, Context, TemplateSyntaxError
|
from django.template import Template, Context, TemplateSyntaxError
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from compressor.conf import settings
|
|
||||||
|
|
||||||
from .base import css_tag
|
from .base import css_tag
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
[tox]
|
[tox]
|
||||||
setupdir = ..
|
setupdir = ..
|
||||||
distribute = false
|
distribute = false
|
||||||
downloadcache = {toxinidir}/_download/
|
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands =
|
commands =
|
||||||
{envpython} {toxinidir}/runtests.py []
|
{envbindir}/coverage erase
|
||||||
coverage html -d {envtmpdir}/coverage
|
{envbindir}/coverage run --branch --include=*compressor* --omit=*test*,*rjsmin*,*cssmin*,*stringformat*,*models* {envbindir}/django-admin.py test {posargs:tests} --settings=tests.settings
|
||||||
|
{envbindir}/coverage report
|
||||||
|
{envbindir}/coverage html -d {envtmpdir}
|
||||||
|
echo "Type the following to open the coverage report: python -m webbrowser -t file://{envtmpdir}/index.html"
|
||||||
|
setenv =
|
||||||
|
PYTHONPATH = {toxinidir}/..
|
||||||
|
downloadcache = {toxworkdir}/_download/
|
||||||
|
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
changedir = ../docs
|
changedir = ../docs
|
||||||
@@ -20,7 +26,7 @@ commands =
|
|||||||
basepython = python2.5
|
basepython = python2.5
|
||||||
deps =
|
deps =
|
||||||
unittest2
|
unittest2
|
||||||
BeautifulSoup
|
BeautifulSoup==3.2.0
|
||||||
html5lib
|
html5lib
|
||||||
coverage
|
coverage
|
||||||
django==1.2.5
|
django==1.2.5
|
||||||
@@ -29,7 +35,7 @@ deps =
|
|||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps =
|
deps =
|
||||||
unittest2
|
unittest2
|
||||||
BeautifulSoup==3.2
|
BeautifulSoup==3.2.0
|
||||||
html5lib
|
html5lib
|
||||||
coverage
|
coverage
|
||||||
mock
|
mock
|
||||||
@@ -39,7 +45,7 @@ deps =
|
|||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
unittest2
|
unittest2
|
||||||
BeautifulSoup==3.2
|
BeautifulSoup==3.2.0
|
||||||
html5lib
|
html5lib
|
||||||
coverage
|
coverage
|
||||||
mock
|
mock
|
||||||
@@ -50,7 +56,7 @@ deps =
|
|||||||
basepython = python2.5
|
basepython = python2.5
|
||||||
deps =
|
deps =
|
||||||
unittest2
|
unittest2
|
||||||
BeautifulSoup==3.2
|
BeautifulSoup==3.2.0
|
||||||
html5lib
|
html5lib
|
||||||
coverage
|
coverage
|
||||||
mock
|
mock
|
||||||
@@ -60,7 +66,7 @@ deps =
|
|||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps =
|
deps =
|
||||||
unittest2
|
unittest2
|
||||||
BeautifulSoup==3.2
|
BeautifulSoup==3.2.0
|
||||||
html5lib
|
html5lib
|
||||||
coverage
|
coverage
|
||||||
mock
|
mock
|
||||||
@@ -70,7 +76,7 @@ deps =
|
|||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
unittest2
|
unittest2
|
||||||
BeautifulSoup==3.2
|
BeautifulSoup==3.2.0
|
||||||
html5lib
|
html5lib
|
||||||
coverage
|
coverage
|
||||||
mock
|
mock
|
||||||
|
|||||||
Reference in New Issue
Block a user