diff --git a/.travis.yml b/.travis.yml
index 839b3e1..e049309 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,11 @@ env:
- DJANGO="Django>=1.4,<1.5"
- DJANGO="Django>=1.5,<1.6"
- DJANGO="Django>=1.6,<1.7"
+- DJANGO="Django>=1.7,<1.8"
+matrix:
+ exclude:
+ - python: "2.6"
+ env: DJANGO="Django>=1.7,<1.8"
install:
- pip install $DJANGO
script:
diff --git a/analytical/templatetags/clickmap.py b/analytical/templatetags/clickmap.py
index 2d0414a..d0189d2 100644
--- a/analytical/templatetags/clickmap.py
+++ b/analytical/templatetags/clickmap.py
@@ -8,13 +8,13 @@ import re
from django.template import Library, Node, TemplateSyntaxError
-from analytical.utils import get_identity, is_internal_ip, disable_html, get_required_setting
+from analytical.utils import is_internal_ip, disable_html, get_required_setting
CLICKMAP_TRACKER_ID_RE = re.compile(r'^\d+$')
TRACKING_CODE = """
""", rendered_tag)
- @override_settings(INTERCOM_APP_ID=SETTING_DELETED)
+ @override_settings(INTERCOM_APP_ID=None)
def test_no_account_number(self):
self.assertRaises(AnalyticalException, IntercomNode)
diff --git a/analytical/tests/test_tag_kiss_insights.py b/analytical/tests/test_tag_kiss_insights.py
index 2626ac7..ea58250 100644
--- a/analytical/tests/test_tag_kiss_insights.py
+++ b/analytical/tests/test_tag_kiss_insights.py
@@ -4,9 +4,10 @@ Tests for the KISSinsights template tags and filters.
from django.contrib.auth.models import User, AnonymousUser
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.kiss_insights import KissInsightsNode
-from analytical.tests.utils import TagTestCase, override_settings, SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -25,11 +26,11 @@ class KissInsightsTagTestCase(TagTestCase):
r = KissInsightsNode().render(Context())
self.assertTrue("//s3.amazonaws.com/ki.js/12345/abc.js" in r, r)
- @override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER=SETTING_DELETED)
+ @override_settings(KISS_INSIGHTS_ACCOUNT_NUMBER=None)
def test_no_account_number(self):
self.assertRaises(AnalyticalException, KissInsightsNode)
- @override_settings(KISS_INSIGHTS_SITE_CODE=SETTING_DELETED)
+ @override_settings(KISS_INSIGHTS_SITE_CODE=None)
def test_no_site_code(self):
self.assertRaises(AnalyticalException, KissInsightsNode)
diff --git a/analytical/tests/test_tag_kiss_metrics.py b/analytical/tests/test_tag_kiss_metrics.py
index d520f52..b5cf2aa 100644
--- a/analytical/tests/test_tag_kiss_metrics.py
+++ b/analytical/tests/test_tag_kiss_metrics.py
@@ -5,9 +5,10 @@ Tests for the KISSmetrics tags and filters.
from django.contrib.auth.models import User, AnonymousUser
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.kiss_metrics import KissMetricsNode
-from analytical.tests.utils import TagTestCase, override_settings, SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -28,7 +29,7 @@ class KissMetricsTagTestCase(TagTestCase):
self.assertTrue("//doug1izaerwt3.cloudfront.net/0123456789abcdef012345"
"6789abcdef01234567.1.js" in r, r)
- @override_settings(KISS_METRICS_API_KEY=SETTING_DELETED)
+ @override_settings(KISS_METRICS_API_KEY=None)
def test_no_api_key(self):
self.assertRaises(AnalyticalException, KissMetricsNode)
diff --git a/analytical/tests/test_tag_mixpanel.py b/analytical/tests/test_tag_mixpanel.py
index 3f61485..e5b1ffb 100644
--- a/analytical/tests/test_tag_mixpanel.py
+++ b/analytical/tests/test_tag_mixpanel.py
@@ -5,9 +5,10 @@ Tests for the Mixpanel tags and filters.
from django.contrib.auth.models import User, AnonymousUser
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.mixpanel import MixpanelNode
-from analytical.tests.utils import TagTestCase, override_settings, SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -29,7 +30,7 @@ class MixpanelTagTestCase(TagTestCase):
"mixpanel.init('0123456789abcdef0123456789abcdef');" in r,
r)
- @override_settings(MIXPANEL_API_TOKEN=SETTING_DELETED)
+ @override_settings(MIXPANEL_API_TOKEN=None)
def test_no_token(self):
self.assertRaises(AnalyticalException, MixpanelNode)
diff --git a/analytical/tests/test_tag_olark.py b/analytical/tests/test_tag_olark.py
index bd93458..ecc3f56 100644
--- a/analytical/tests/test_tag_olark.py
+++ b/analytical/tests/test_tag_olark.py
@@ -4,9 +4,10 @@ Tests for the Olark template tags and filters.
from django.contrib.auth.models import User, AnonymousUser
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.olark import OlarkNode
-from analytical.tests.utils import TagTestCase, override_settings, SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -24,7 +25,7 @@ class OlarkTestCase(TagTestCase):
r = OlarkNode().render(Context())
self.assertTrue("olark.identify('1234-567-89-0123');" in r, r)
- @override_settings(OLARK_SITE_ID=SETTING_DELETED)
+ @override_settings(OLARK_SITE_ID=None)
def test_no_site_id(self):
self.assertRaises(AnalyticalException, OlarkNode)
diff --git a/analytical/tests/test_tag_optimizely.py b/analytical/tests/test_tag_optimizely.py
index 412eb46..a1cce26 100644
--- a/analytical/tests/test_tag_optimizely.py
+++ b/analytical/tests/test_tag_optimizely.py
@@ -4,9 +4,10 @@ Tests for the Optimizely template tags and filters.
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.optimizely import OptimizelyNode
-from analytical.tests.utils import TagTestCase, override_settings, SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -26,7 +27,7 @@ class OptimizelyTagTestCase(TagTestCase):
'',
OptimizelyNode().render(Context()))
- @override_settings(OPTIMIZELY_ACCOUNT_NUMBER=SETTING_DELETED)
+ @override_settings(OPTIMIZELY_ACCOUNT_NUMBER=None)
def test_no_account_number(self):
self.assertRaises(AnalyticalException, OptimizelyNode)
diff --git a/analytical/tests/test_tag_performable.py b/analytical/tests/test_tag_performable.py
index 5e5c805..befee4b 100644
--- a/analytical/tests/test_tag_performable.py
+++ b/analytical/tests/test_tag_performable.py
@@ -5,9 +5,10 @@ Tests for the Performable template tags and filters.
from django.contrib.auth.models import User, AnonymousUser
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.performable import PerformableNode
-from analytical.tests.utils import TagTestCase, override_settings, SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -25,7 +26,7 @@ class PerformableTagTestCase(TagTestCase):
r = PerformableNode().render(Context())
self.assertTrue('/performable/pax/123ABC.js' in r, r)
- @override_settings(PERFORMABLE_API_KEY=SETTING_DELETED)
+ @override_settings(PERFORMABLE_API_KEY=None)
def test_no_api_key(self):
self.assertRaises(AnalyticalException, PerformableNode)
diff --git a/analytical/tests/test_tag_piwik.py b/analytical/tests/test_tag_piwik.py
index e06a91c..35f6d54 100644
--- a/analytical/tests/test_tag_piwik.py
+++ b/analytical/tests/test_tag_piwik.py
@@ -4,10 +4,10 @@ Tests for the Piwik template tags and filters.
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.piwik import PiwikNode
-from analytical.tests.utils import TagTestCase, override_settings, \
- SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -38,11 +38,11 @@ class PiwikTagTestCase(TagTestCase):
self.assertTrue(' ? "https" : "http") + "://example.com/piwik/";' in r,
r)
- @override_settings(PIWIK_DOMAIN_PATH=SETTING_DELETED)
+ @override_settings(PIWIK_DOMAIN_PATH=None)
def test_no_domain(self):
self.assertRaises(AnalyticalException, PiwikNode)
- @override_settings(PIWIK_SITE_ID=SETTING_DELETED)
+ @override_settings(PIWIK_SITE_ID=None)
def test_no_siteid(self):
self.assertRaises(AnalyticalException, PiwikNode)
diff --git a/analytical/tests/test_tag_reinvigorate.py b/analytical/tests/test_tag_reinvigorate.py
index f3c4111..c23febd 100644
--- a/analytical/tests/test_tag_reinvigorate.py
+++ b/analytical/tests/test_tag_reinvigorate.py
@@ -7,10 +7,10 @@ import re
from django.contrib.auth.models import User, AnonymousUser
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.reinvigorate import ReinvigorateNode
-from analytical.tests.utils import TagTestCase, override_settings, \
- SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -28,7 +28,7 @@ class ReinvigorateTagTestCase(TagTestCase):
r = ReinvigorateNode().render(Context({}))
self.assertTrue('reinvigorate.track("12345-abcdefghij");' in r, r)
- @override_settings(REINVIGORATE_TRACKING_ID=SETTING_DELETED)
+ @override_settings(REINVIGORATE_TRACKING_ID=None)
def test_no_tracking_id(self):
self.assertRaises(AnalyticalException, ReinvigorateNode)
diff --git a/analytical/tests/test_tag_snapengage.py b/analytical/tests/test_tag_snapengage.py
index 931b1fb..07b96bc 100644
--- a/analytical/tests/test_tag_snapengage.py
+++ b/analytical/tests/test_tag_snapengage.py
@@ -4,14 +4,14 @@ Tests for the SnapEngage template tags and filters.
from django.contrib.auth.models import User, AnonymousUser
from django.template import Context
+from django.test.utils import override_settings
from django.utils import translation
from analytical.templatetags.snapengage import SnapEngageNode, \
BUTTON_STYLE_LIVE, BUTTON_STYLE_DEFAULT, BUTTON_STYLE_NONE, \
BUTTON_LOCATION_LEFT, BUTTON_LOCATION_RIGHT, BUTTON_LOCATION_TOP, \
BUTTON_LOCATION_BOTTOM, FORM_POSITION_TOP_LEFT
-from analytical.tests.utils import TagTestCase, override_settings, \
- SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -41,7 +41,7 @@ class SnapEngageTestCase(TagTestCase):
'SnapABug.addButton("ec329c69-0bf0-4db8-9b77-3f8150fb977e","0",'
'"55%");' in r, r)
- @override_settings(SNAPENGAGE_WIDGET_ID=SETTING_DELETED)
+ @override_settings(SNAPENGAGE_WIDGET_ID=None)
def test_no_site_id(self):
self.assertRaises(AnalyticalException, SnapEngageNode)
diff --git a/analytical/tests/test_tag_spring_metrics.py b/analytical/tests/test_tag_spring_metrics.py
index a69cb5d..5256d55 100644
--- a/analytical/tests/test_tag_spring_metrics.py
+++ b/analytical/tests/test_tag_spring_metrics.py
@@ -7,10 +7,10 @@ import re
from django.contrib.auth.models import User, AnonymousUser
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.spring_metrics import SpringMetricsNode
-from analytical.tests.utils import TagTestCase, override_settings, \
- SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -28,7 +28,7 @@ class SpringMetricsTagTestCase(TagTestCase):
r = SpringMetricsNode().render(Context({}))
self.assertTrue("_springMetq.push(['id', '12345678']);" in r, r)
- @override_settings(SPRING_METRICS_TRACKING_ID=SETTING_DELETED)
+ @override_settings(SPRING_METRICS_TRACKING_ID=None)
def test_no_site_id(self):
self.assertRaises(AnalyticalException, SpringMetricsNode)
diff --git a/analytical/tests/test_tag_uservoice.py b/analytical/tests/test_tag_uservoice.py
index bebce83..5ff6a8b 100644
--- a/analytical/tests/test_tag_uservoice.py
+++ b/analytical/tests/test_tag_uservoice.py
@@ -2,13 +2,11 @@
Tests for the UserVoice tags and filters.
"""
-from django.contrib.auth.models import User, AnonymousUser
-from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.uservoice import UserVoiceNode
-from analytical.tests.utils import TagTestCase, override_settings, \
- SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -32,7 +30,7 @@ class UserVoiceTagTestCase(TagTestCase):
r = self.render_tag('uservoice', 'uservoice')
self.assertIn("widget.uservoice.com/abcdefghijklmnopqrst.js", r)
- @override_settings(USERVOICE_WIDGET_KEY=SETTING_DELETED)
+ @override_settings(USERVOICE_WIDGET_KEY=None)
def test_no_key(self):
self.assertRaises(AnalyticalException, UserVoiceNode)
diff --git a/analytical/tests/test_tag_woopra.py b/analytical/tests/test_tag_woopra.py
index 42dd8fa..8eb4ec2 100644
--- a/analytical/tests/test_tag_woopra.py
+++ b/analytical/tests/test_tag_woopra.py
@@ -5,10 +5,10 @@ Tests for the Woopra template tags and filters.
from django.contrib.auth.models import User, AnonymousUser
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.templatetags.woopra import WoopraNode
-from analytical.tests.utils import TagTestCase, override_settings, \
- SETTING_DELETED
+from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
@@ -26,7 +26,7 @@ class WoopraTagTestCase(TagTestCase):
r = WoopraNode().render(Context({}))
self.assertTrue('var woo_settings = {"domain": "example.com"};' in r, r)
- @override_settings(WOOPRA_DOMAIN=SETTING_DELETED)
+ @override_settings(WOOPRA_DOMAIN=None)
def test_no_domain(self):
self.assertRaises(AnalyticalException, WoopraNode)
diff --git a/analytical/tests/test_utils.py b/analytical/tests/test_utils.py
index 071059e..53f59d5 100644
--- a/analytical/tests/test_utils.py
+++ b/analytical/tests/test_utils.py
@@ -3,41 +3,25 @@ Tests for the analytical.utils module.
"""
from django.conf import settings
-from django.contrib.sites.models import Site
from django.http import HttpRequest
from django.template import Context
+from django.test.utils import override_settings
from analytical.utils import (
get_domain, is_internal_ip, get_required_setting, AnalyticalException)
-from analytical.tests.utils import (
- TestCase, override_settings, with_apps, SETTING_DELETED)
+from analytical.tests.utils import TestCase
class SettingDeletedTestCase(TestCase):
- @override_settings(USER_ID=SETTING_DELETED)
- def test_deleted_setting_raises_exception(self):
- self.assertRaises(AttributeError, getattr, settings, "USER_ID")
- @override_settings(USER_ID=1)
- def test_only_disable_within_context_manager(self):
- """
- Make sure deleted settings returns once the block exits.
- """
- self.assertEqual(settings.USER_ID, 1)
-
- with override_settings(USER_ID=SETTING_DELETED):
- self.assertRaises(AttributeError, getattr, settings, "USER_ID")
-
- self.assertEqual(settings.USER_ID, 1)
-
- @override_settings(USER_ID=SETTING_DELETED)
+ @override_settings(USER_ID=None)
def test_get_required_setting(self):
"""
Make sure using get_required_setting fails in the right place.
"""
# only available in python >= 2.7
if hasattr(self, 'assertRaisesRegexp'):
- with self.assertRaisesRegexp(AnalyticalException, "^USER_ID setting: not found$"):
+ with self.assertRaisesRegexp(AnalyticalException, "^USER_ID setting is set to None$"):
user_id = get_required_setting("USER_ID", "\d+", "invalid USER_ID")
else:
self.assertRaises(AnalyticalException,
diff --git a/analytical/tests/utils.py b/analytical/tests/utils.py
index 8c29fec..ee95c51 100644
--- a/analytical/tests/utils.py
+++ b/analytical/tests/utils.py
@@ -4,103 +4,8 @@ Testing utilities.
from __future__ import with_statement
-import copy
-
-from django.conf import settings, UserSettingsHolder
-from django.core.management import call_command
-from django.db.models import loading
from django.template import Template, Context, RequestContext
from django.test.testcases import TestCase
-from django.utils.functional import wraps
-
-
-SETTING_DELETED = object()
-
-
-# Backported adapted from Django trunk (r16377)
-class override_settings(object):
- """
- Temporarily override Django settings.
-
- Can be used as either a decorator on test classes/functions or as
- a context manager inside test functions.
-
- In either case it temporarily overrides django.conf.settings so
- that you can test how code acts when certain settings are set to
- certain values or deleted altogether with SETTING_DELETED.
-
- >>> @override_settings(FOOBAR=42)
- >>> class TestBaz(TestCase):
- >>> # settings.FOOBAR == 42 for all tests
- >>>
- >>> @override_settings(FOOBAR=43)
- >>> def test_widget(self):
- >>> # settings.FOOBAR == 43 for just this test
- >>>
- >>> with override_settings(FOOBAR=44):
- >>> # settings.FOOBAR == 44 just inside this block
- >>> pass
- >>>
- >>> # settings.FOOBAR == 43 inside the test
- """
- def __init__(self, **kwargs):
- self.options = kwargs
- self.wrapped = settings._wrapped
-
- def __enter__(self):
- self.enable()
-
- def __exit__(self, exc_type, exc_value, traceback):
- self.disable()
-
- def __call__(self, test_func):
- from django.test import TransactionTestCase
- if isinstance(test_func, type) and issubclass(test_func, TransactionTestCase):
- # When decorating a class, we need to construct a new class
- # with the same name so that the test discovery tools can
- # get a useful name.
- def _pre_setup(innerself):
- self.enable()
- test_func._pre_setup(innerself)
- def _post_teardown(innerself):
- test_func._post_teardown(innerself)
- self.disable()
- inner = type(
- test_func.__name__,
- (test_func,),
- {
- '_pre_setup': _pre_setup,
- '_post_teardown': _post_teardown,
- '__module__': test_func.__module__,
- })
- else:
- @wraps(test_func)
- def inner(*args, **kwargs):
- with self:
- return test_func(*args, **kwargs)
- return inner
-
- def enable(self):
- class OverrideSettingsHolder(UserSettingsHolder):
- def __getattr__(self, name):
- if name == "default_settings":
- return self.__dict__["default_settings"]
- return getattr(self.default_settings, name)
-
- override = OverrideSettingsHolder(copy.copy(settings._wrapped))
- for key, new_value in self.options.items():
- if new_value is SETTING_DELETED:
- try:
- delattr(override.default_settings, key)
- except AttributeError:
- pass
- else:
- setattr(override, key, new_value)
- settings._wrapped = override
-
- def disable(self):
- settings._wrapped = self.wrapped
-
def run_tests():
"""
@@ -109,30 +14,19 @@ def run_tests():
Sets the return code to the number of failed tests.
"""
import sys
- from django.test.simple import DjangoTestSuiteRunner
- runner = DjangoTestSuiteRunner()
+ import django
+ try:
+ django.setup()
+ except AttributeError:
+ pass
+ try:
+ from django.test.runner import DiscoverRunner as TestRunner
+ except ImportError:
+ from django.test.simple import DjangoTestSuiteRunner as TestRunner
+ runner = TestRunner()
sys.exit(runner.run_tests(["analytical"]))
-def with_apps(*apps):
- """
- Class decorator that makes sure the passed apps are present in
- INSTALLED_APPS.
- """
- apps_set = set(settings.INSTALLED_APPS)
- apps_set.update(apps)
- return override_settings(INSTALLED_APPS=list(apps_set))
-
-
-def without_apps(*apps):
- """
- Class decorator that makes sure the passed apps are not present in
- INSTALLED_APPS.
- """
- apps_list = [a for a in settings.INSTALLED_APPS if a not in apps]
- return override_settings(INSTALLED_APPS=apps_list)
-
-
class TagTestCase(TestCase):
"""
Tests for a template tag.
diff --git a/analytical/utils.py b/analytical/utils.py
index db31706..f8d4a32 100644
--- a/analytical/utils.py
+++ b/analytical/utils.py
@@ -22,6 +22,8 @@ def get_required_setting(setting, value_re, invalid_msg):
value = getattr(settings, setting)
except AttributeError:
raise AnalyticalException("%s setting: not found" % setting)
+ if value is None:
+ raise AnalyticalException("%s setting is set to None" % setting)
value = str(value)
if not value_re.search(value):
raise AnalyticalException("%s setting: %s: '%s'"
diff --git a/setup.py b/setup.py
index 472ac3a..e016ca5 100644
--- a/setup.py
+++ b/setup.py
@@ -69,6 +69,8 @@ setup(
'Programming Language :: Python',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
],
platforms = ['any'],
url = 'http://github.com/jcassee/django-analytical',
diff --git a/tox.ini b/tox.ini
index 6f705c5..60765da 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,8 @@
[tox]
envlist =
py2.6-django1.4,py2.6-django1.5,py2.6-django1.6,
- py2.7-django1.4,py2.7-django1.5,py2.7-django1.6
+ py2.7-django1.4,py2.7-django1.5,py2.7-django1.6,
+ py2.7-django1.7
[testenv]
commands = python -Wall setup.py test
@@ -45,3 +46,7 @@ deps = Django>=1.6,<1.7
[testenv:py2.7-django1.6]
basepython = python2.7
deps = Django>=1.6,<1.7
+
+[testenv:py2.7-django1.7]
+basepython = python2.7
+deps = Django>=1.7,<1.8