diff --git a/compressor/base.py b/compressor/base.py index 25f35f2..527734d 100644 --- a/compressor/base.py +++ b/compressor/base.py @@ -2,12 +2,13 @@ from __future__ import with_statement import os import codecs +from django.conf import settings from django.core.files.base import ContentFile from django.template.loader import render_to_string from django.utils.encoding import smart_unicode from compressor.cache import get_hexdigest, get_mtime -from compressor.conf import settings + from compressor.exceptions import CompressorError, UncompressableFileError from compressor.filters import CompilerFilter from compressor.storage import default_storage diff --git a/compressor/cache.py b/compressor/cache.py index 5f45506..3810d64 100644 --- a/compressor/cache.py +++ b/compressor/cache.py @@ -2,12 +2,12 @@ import os import socket import time +from django.conf import settings from django.core.cache import get_cache from django.utils.encoding import smart_str from django.utils.hashcompat import md5_constructor from django.utils.importlib import import_module -from compressor.conf import settings from compressor.utils import get_mod_func diff --git a/compressor/css.py b/compressor/css.py index 260bae2..d7b2849 100644 --- a/compressor/css.py +++ b/compressor/css.py @@ -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.exceptions import UncompressableFileError diff --git a/compressor/filters/base.py b/compressor/filters/base.py index 51c7940..4ec476c 100644 --- a/compressor/filters/base.py +++ b/compressor/filters/base.py @@ -3,11 +3,11 @@ import os import logging import subprocess import tempfile +from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.files.temp import NamedTemporaryFile from django.utils.importlib import import_module -from compressor.conf import settings from compressor.exceptions import FilterError from compressor.utils import get_mod_func from compressor.utils.stringformat import FormattableString as fstr diff --git a/compressor/filters/closure.py b/compressor/filters/closure.py index d229bcb..e0ee65a 100644 --- a/compressor/filters/closure.py +++ b/compressor/filters/closure.py @@ -1,4 +1,5 @@ -from compressor.conf import settings +from django.conf import settings + from compressor.filters import CompilerFilter diff --git a/compressor/filters/css_default.py b/compressor/filters/css_default.py index 6f2ffb9..c77cfb9 100644 --- a/compressor/filters/css_default.py +++ b/compressor/filters/css_default.py @@ -2,8 +2,9 @@ import os import re import posixpath +from django.conf import settings + from compressor.cache import get_hexdigest, get_hashed_mtime -from compressor.conf import settings from compressor.filters import FilterBase from compressor.utils import staticfiles diff --git a/compressor/filters/csstidy.py b/compressor/filters/csstidy.py index 4b7e4c7..5ab0d9b 100644 --- a/compressor/filters/csstidy.py +++ b/compressor/filters/csstidy.py @@ -1,4 +1,5 @@ -from compressor.conf import settings +from django.conf import settings + from compressor.filters import CompilerFilter diff --git a/compressor/filters/datauri.py b/compressor/filters/datauri.py index 9425d72..ca6f706 100644 --- a/compressor/filters/datauri.py +++ b/compressor/filters/datauri.py @@ -3,7 +3,8 @@ import re import mimetypes from base64 import b64encode -from compressor.conf import settings +from django.conf import settings + from compressor.filters import FilterBase diff --git a/compressor/filters/yui.py b/compressor/filters/yui.py index 60fd1f7..cf34099 100644 --- a/compressor/filters/yui.py +++ b/compressor/filters/yui.py @@ -1,4 +1,5 @@ -from compressor.conf import settings +from django.conf import settings + from compressor.filters import CompilerFilter diff --git a/compressor/js.py b/compressor/js.py index ad5c8b1..4ad5e84 100644 --- a/compressor/js.py +++ b/compressor/js.py @@ -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.exceptions import UncompressableFileError diff --git a/compressor/management/commands/compress.py b/compressor/management/commands/compress.py index 86e27e6..552809e 100644 --- a/compressor/management/commands/compress.py +++ b/compressor/management/commands/compress.py @@ -9,6 +9,7 @@ try: except ImportError: from StringIO import StringIO +from django.conf import settings from django.core.management.base import NoArgsCommand, CommandError from django.template import Context, Template, TemplateDoesNotExist, TemplateSyntaxError from django.utils.datastructures import SortedDict @@ -22,7 +23,6 @@ except ImportError: CachedLoader = None from compressor.cache import cache, get_offline_cachekey -from compressor.conf import settings from compressor.exceptions import OfflineGenerationError from compressor.templatetags.compress import CompressorNode from compressor.utils import walk, any diff --git a/compressor/management/commands/mtime_cache.py b/compressor/management/commands/mtime_cache.py index 88deab0..e9d80b2 100644 --- a/compressor/management/commands/mtime_cache.py +++ b/compressor/management/commands/mtime_cache.py @@ -2,10 +2,10 @@ import fnmatch import os from optparse import make_option +from django.conf import settings from django.core.management.base import NoArgsCommand, CommandError from compressor.cache import cache, get_mtime, get_mtime_cachekey -from compressor.conf import settings from compressor.utils import walk diff --git a/compressor/conf.py b/compressor/models.py similarity index 82% rename from compressor/conf.py rename to compressor/models.py index 2011531..ee1b9be 100644 --- a/compressor/conf.py +++ b/compressor/models.py @@ -1,11 +1,12 @@ import os 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 compressor.utils.settings import AppSettings +from appconf import AppConf -class CompressorSettings(AppSettings): + +class CompressorConf(AppConf): # Main switch ENABLED = False # Allows changing verbosity from the settings. @@ -60,14 +61,17 @@ class CompressorSettings(AppSettings): # The context to be used when compressing the files "offline" OFFLINE_CONTEXT = {} + class Meta: + prefix = 'compress' + def configure_enabled(self, value): - return value or not global_settings.DEBUG + return value or not settings.DEBUG def configure_root(self, value): if value is None: - value = getattr(global_settings, 'STATIC_ROOT', None) + value = getattr(settings, 'STATIC_ROOT', None) if not value: - value = global_settings.MEDIA_ROOT + value = settings.MEDIA_ROOT if not value: raise ImproperlyConfigured( "The COMPRESS_ROOT setting must be set.") @@ -76,9 +80,9 @@ class CompressorSettings(AppSettings): def configure_url(self, value): # Uses Django 1.3's STATIC_URL by default or falls back to MEDIA_URL if value is None: - value = getattr(global_settings, "STATIC_URL", None) + value = getattr(settings, "STATIC_URL", None) if not value: - value = global_settings.MEDIA_URL + value = settings.MEDIA_URL if not value.endswith("/"): raise ImproperlyConfigured("The URL settings (e.g. COMPRESS_URL) " "must have a trailing slash.") @@ -87,11 +91,11 @@ class CompressorSettings(AppSettings): def configure_cache_backend(self, value): if value is None: # 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" else: # falling back to the old CACHE_BACKEND setting - value = getattr(global_settings, "CACHE_BACKEND", None) + value = getattr(settings, "CACHE_BACKEND", None) if not value: raise ImproperlyConfigured( "Please specify a cache backend in your settings.") @@ -100,11 +104,11 @@ class CompressorSettings(AppSettings): def configure_offline_context(self, value): if not 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 - if getattr(global_settings, "STATIC_URL", None): - value["STATIC_URL"] = global_settings.STATIC_URL + if getattr(settings, "STATIC_URL", None): + value["STATIC_URL"] = settings.STATIC_URL return value def configure_precompilers(self, value): @@ -112,5 +116,3 @@ class CompressorSettings(AppSettings): raise ImproperlyConfigured("The COMPRESS_PRECOMPILERS setting " "must be a list or tuple. Check for missing commas.") return value - -settings = CompressorSettings(prefix="COMPRESS") diff --git a/compressor/storage.py b/compressor/storage.py index a8cfac1..5d895bb 100644 --- a/compressor/storage.py +++ b/compressor/storage.py @@ -2,11 +2,10 @@ import gzip from os import path from datetime import datetime +from django.conf import settings from django.core.files.storage import FileSystemStorage, get_storage_class from django.utils.functional import LazyObject -from compressor.conf import settings - class CompressorFileStorage(FileSystemStorage): """ diff --git a/compressor/templatetags/compress.py b/compressor/templatetags/compress.py index 8e8af84..e84e8c9 100644 --- a/compressor/templatetags/compress.py +++ b/compressor/templatetags/compress.py @@ -1,9 +1,9 @@ from django import template +from django.conf import settings from django.core.exceptions import ImproperlyConfigured from compressor.cache import (cache, cache_get, cache_set, get_offline_cachekey, get_templatetag_cachekey) -from compressor.conf import settings from compressor.utils import get_class register = template.Library() diff --git a/compressor/utils/settings.py b/compressor/utils/settings.py deleted file mode 100644 index 736225c..0000000 --- a/compressor/utils/settings.py +++ /dev/null @@ -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_`` 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() - diff --git a/setup.py b/setup.py index c343fd4..d23665c 100644 --- a/setup.py +++ b/setup.py @@ -121,4 +121,7 @@ setup( 'Topic :: Internet :: WWW/HTTP', ], zip_safe = False, + install_requires=[ + 'django-appconf >= 0.4', + ], ) diff --git a/tests/settings.py b/tests/settings.py new file mode 100644 index 0000000..e3c819b --- /dev/null +++ b/tests/settings.py @@ -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'), +) diff --git a/tests/tests/base.py b/tests/tests/base.py index 8930b2f..228d6f9 100644 --- a/tests/tests/base.py +++ b/tests/tests/base.py @@ -4,12 +4,11 @@ import re from BeautifulSoup import BeautifulSoup +from django.conf import settings from django.core.cache.backends import locmem from django.test import TestCase 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.js import JsCompressor @@ -22,6 +21,7 @@ def css_tag(href, **kwargs): test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + class CompressorTestCase(TestCase): def setUp(self): @@ -81,7 +81,7 @@ class CompressorTestCase(TestCase): def test_js_split(self): out = [ (SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), u'js/one.js', ''), - (SOURCE_HUNK, u'obj.value = "value";', None, '') + (SOURCE_HUNK, u'obj.value = "value";', None, ''), ] 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] @@ -127,7 +127,6 @@ class CompressorTestCase(TestCase): settings.COMPRESS_OUTPUT_DIR = old_output_dir - class CssMediaTestCase(TestCase): def setUp(self): self.css = """\ @@ -151,8 +150,6 @@ class CssMediaTestCase(TestCase): self.assertEqual(media, [l.get('media', None) for l in links]) - - class VerboseTestCase(CompressorTestCase): def setUp(self): @@ -165,5 +162,3 @@ class CacheBackendTestCase(CompressorTestCase): def test_correct_backend(self): from compressor.cache import cache self.assertEqual(cache.__class__, locmem.CacheClass) - - diff --git a/tests/tests/filters.py b/tests/tests/filters.py index f6cf287..5ef0644 100644 --- a/tests/tests/filters.py +++ b/tests/tests/filters.py @@ -3,10 +3,10 @@ import os import sys from unittest2 import skipIf +from django.conf import settings from django.test import TestCase from compressor.cache import get_hashed_mtime -from compressor.conf import settings from compressor.css import CssCompressor from compressor.utils import find_command from compressor.filters.base import CompilerFilter diff --git a/tests/tests/offline.py b/tests/tests/offline.py index e347c9a..3fc642c 100644 --- a/tests/tests/offline.py +++ b/tests/tests/offline.py @@ -1,10 +1,10 @@ from __future__ import with_statement import os +from django.conf import settings from django.template import Template, Context from django.test import TestCase -from compressor.conf import settings from compressor.management.commands.compress import Command as CompressCommand from .base import test_dir, css_tag diff --git a/tests/tests/parsers.py b/tests/tests/parsers.py index e1e4dce..e76a447 100644 --- a/tests/tests/parsers.py +++ b/tests/tests/parsers.py @@ -2,8 +2,6 @@ from __future__ import with_statement import os from unittest2 import skipIf -from BeautifulSoup import BeautifulSoup - try: import lxml except ImportError: @@ -20,7 +18,8 @@ except ImportError: BeautifulSoup = None -from compressor.conf import settings +from django.conf import settings + from compressor.base import SOURCE_HUNK, SOURCE_FILE from .base import CompressorTestCase diff --git a/tests/tests/storages.py b/tests/tests/storages.py index 7311bae..d7dae0a 100644 --- a/tests/tests/storages.py +++ b/tests/tests/storages.py @@ -1,10 +1,10 @@ from __future__ import with_statement +from django.conf import settings from django.core.files.storage import get_storage_class from django.test import TestCase from compressor import base -from compressor.conf import settings from .base import css_tag from .templatetags import render diff --git a/tests/tests/templatetags.py b/tests/tests/templatetags.py index 18d242a..7b3fd5d 100644 --- a/tests/tests/templatetags.py +++ b/tests/tests/templatetags.py @@ -1,10 +1,9 @@ from __future__ import with_statement +from django.conf import settings from django.template import Template, Context, TemplateSyntaxError from django.test import TestCase -from compressor.conf import settings - from .base import css_tag diff --git a/tests/tox.ini b/tests/tox.ini index f235565..41fc7f3 100644 --- a/tests/tox.ini +++ b/tests/tox.ini @@ -1,12 +1,18 @@ [tox] setupdir = .. distribute = false -downloadcache = {toxinidir}/_download/ [testenv] commands = - {envpython} {toxinidir}/runtests.py [] - coverage html -d {envtmpdir}/coverage + {envbindir}/coverage erase + {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] changedir = ../docs @@ -20,7 +26,7 @@ commands = basepython = python2.5 deps = unittest2 - BeautifulSoup + BeautifulSoup==3.2.0 html5lib coverage django==1.2.5 @@ -29,7 +35,7 @@ deps = basepython = python2.6 deps = unittest2 - BeautifulSoup + BeautifulSoup==3.2.0 html5lib coverage django==1.2.5 @@ -38,7 +44,7 @@ deps = basepython = python2.7 deps = unittest2 - BeautifulSoup + BeautifulSoup==3.2.0 html5lib coverage django==1.2.5 @@ -48,7 +54,7 @@ deps = basepython = python2.5 deps = unittest2 - BeautifulSoup + BeautifulSoup==3.2.0 html5lib coverage django==1.3 @@ -57,7 +63,7 @@ deps = basepython = python2.6 deps = unittest2 - BeautifulSoup + BeautifulSoup==3.2.0 html5lib coverage django==1.3 @@ -66,7 +72,7 @@ deps = basepython = python2.7 deps = unittest2 - BeautifulSoup + BeautifulSoup==3.2.0 html5lib coverage django==1.3