Stop testing for inclusion in INSTALLED_APPS.

Removed some exception masking in the comments app that was harmful and
couldn't be preserved easily.
This commit is contained in:
Aymeric Augustin 2013-12-19 21:57:09 +01:00
parent 70c9654d45
commit 9cdf1f6d54
10 changed files with 66 additions and 65 deletions

View File

@ -1,9 +1,9 @@
from django.conf import settings from django.core.apps import app_cache
from django.template import Library from django.template import Library
register = Library() register = Library()
if 'django.contrib.staticfiles' in settings.INSTALLED_APPS: if app_cache.has_app('django.contrib.staticfiles'):
from django.contrib.staticfiles.templatetags.staticfiles import static from django.contrib.staticfiles.templatetags.staticfiles import static
else: else:
from django.templatetags.static import static from django.templatetags.static import static

View File

@ -2,6 +2,7 @@ from importlib import import_module
import warnings import warnings
from django.conf import settings from django.conf import settings
from django.core import urlresolvers from django.core import urlresolvers
from django.core.apps import app_cache
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.contrib.comments.models import Comment from django.contrib.comments.models import Comment
from django.contrib.comments.forms import CommentForm from django.contrib.comments.forms import CommentForm
@ -14,20 +15,12 @@ def get_comment_app():
""" """
Get the comment app (i.e. "django.contrib.comments") as defined in the settings Get the comment app (i.e. "django.contrib.comments") as defined in the settings
""" """
# Make sure the app's in INSTALLED_APPS
comments_app = get_comment_app_name()
if comments_app not in settings.INSTALLED_APPS:
raise ImproperlyConfigured("The COMMENTS_APP (%r) "\
"must be in INSTALLED_APPS" % settings.COMMENTS_APP)
# Try to import the package
try: try:
package = import_module(comments_app) app_config = app_cache.get_app_config(get_comment_app_name().rpartition(".")[2])
except ImportError as e: except LookupError:
raise ImproperlyConfigured("The COMMENTS_APP setting refers to "\ raise ImproperlyConfigured("The COMMENTS_APP (%r) "
"a non-existing package. (%s)" % e) "must be in INSTALLED_APPS" % settings.COMMENTS_APP)
return app_config.app_module
return package
def get_comment_app_name(): def get_comment_app_name():
""" """

View File

@ -1,4 +1,4 @@
from unittest import skipIf from unittest import skipUnless
from django import http from django import http
from django.conf import settings, global_settings from django.conf import settings, global_settings
@ -7,14 +7,15 @@ from django.contrib.messages.api import MessageFailure
from django.contrib.messages.constants import DEFAULT_LEVELS from django.contrib.messages.constants import DEFAULT_LEVELS
from django.contrib.messages.storage import default_storage, base from django.contrib.messages.storage import default_storage, base
from django.contrib.messages.storage.base import Message from django.contrib.messages.storage.base import Message
from django.core.apps import app_cache
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test.utils import override_settings from django.test.utils import override_settings
from django.utils.translation import ugettext_lazy from django.utils.translation import ugettext_lazy
def skipUnlessAuthIsInstalled(func): def skipUnlessAuthIsInstalled(func):
return skipIf( return skipUnless(
'django.contrib.auth' not in settings.INSTALLED_APPS, app_cache.has_app('django.contrib.auth'),
"django.contrib.auth isn't installed")(func) "django.contrib.auth isn't installed")(func)
@ -219,8 +220,6 @@ class BaseTests(object):
self.assertContains(response, msg) self.assertContains(response, msg)
@override_settings( @override_settings(
INSTALLED_APPS=filter(
lambda app: app != 'django.contrib.messages', settings.INSTALLED_APPS),
MIDDLEWARE_CLASSES=filter( MIDDLEWARE_CLASSES=filter(
lambda m: 'MessageMiddleware' not in m, settings.MIDDLEWARE_CLASSES), lambda m: 'MessageMiddleware' not in m, settings.MIDDLEWARE_CLASSES),
TEMPLATE_CONTEXT_PROCESSORS=filter( TEMPLATE_CONTEXT_PROCESSORS=filter(
@ -233,19 +232,18 @@ class BaseTests(object):
Tests that, when the middleware is disabled, an exception is raised Tests that, when the middleware is disabled, an exception is raised
when one attempts to store a message. when one attempts to store a message.
""" """
data = { with app_cache._without_app('django.contrib.messages'):
'messages': ['Test message %d' % x for x in range(5)], data = {
} 'messages': ['Test message %d' % x for x in range(5)],
reverse('django.contrib.messages.tests.urls.show') }
for level in ('debug', 'info', 'success', 'warning', 'error'): reverse('django.contrib.messages.tests.urls.show')
add_url = reverse('django.contrib.messages.tests.urls.add', for level in ('debug', 'info', 'success', 'warning', 'error'):
args=(level,)) add_url = reverse('django.contrib.messages.tests.urls.add',
self.assertRaises(MessageFailure, self.client.post, add_url, args=(level,))
data, follow=True) self.assertRaises(MessageFailure, self.client.post, add_url,
data, follow=True)
@override_settings( @override_settings(
INSTALLED_APPS=filter(
lambda app: app != 'django.contrib.messages', settings.INSTALLED_APPS),
MIDDLEWARE_CLASSES=filter( MIDDLEWARE_CLASSES=filter(
lambda m: 'MessageMiddleware' not in m, settings.MIDDLEWARE_CLASSES), lambda m: 'MessageMiddleware' not in m, settings.MIDDLEWARE_CLASSES),
TEMPLATE_CONTEXT_PROCESSORS=filter( TEMPLATE_CONTEXT_PROCESSORS=filter(
@ -258,17 +256,18 @@ class BaseTests(object):
Tests that, when the middleware is disabled, an exception is not Tests that, when the middleware is disabled, an exception is not
raised if 'fail_silently' = True raised if 'fail_silently' = True
""" """
data = { with app_cache._without_app('django.contrib.messages'):
'messages': ['Test message %d' % x for x in range(5)], data = {
'fail_silently': True, 'messages': ['Test message %d' % x for x in range(5)],
} 'fail_silently': True,
show_url = reverse('django.contrib.messages.tests.urls.show') }
for level in ('debug', 'info', 'success', 'warning', 'error'): show_url = reverse('django.contrib.messages.tests.urls.show')
add_url = reverse('django.contrib.messages.tests.urls.add', for level in ('debug', 'info', 'success', 'warning', 'error'):
args=(level,)) add_url = reverse('django.contrib.messages.tests.urls.add',
response = self.client.post(add_url, data, follow=True) args=(level,))
self.assertRedirects(response, show_url) response = self.client.post(add_url, data, follow=True)
self.assertFalse('messages' in response.context) self.assertRedirects(response, show_url)
self.assertFalse('messages' in response.context)
def stored_messages_count(self, storage, response): def stored_messages_count(self, storage, response):
""" """

View File

@ -3,6 +3,7 @@ from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.contrib.redirects.models import Redirect from django.contrib.redirects.models import Redirect
from django.contrib.sites.models import get_current_site from django.contrib.sites.models import get_current_site
from django.core.apps import app_cache
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django import http from django import http
@ -14,7 +15,7 @@ class RedirectFallbackMiddleware(object):
response_redirect_class = http.HttpResponsePermanentRedirect response_redirect_class = http.HttpResponsePermanentRedirect
def __init__(self): def __init__(self):
if 'django.contrib.sites' not in settings.INSTALLED_APPS: if not app_cache.has_app('django.contrib.sites'):
raise ImproperlyConfigured( raise ImproperlyConfigured(
"You cannot use RedirectFallbackMiddleware when " "You cannot use RedirectFallbackMiddleware when "
"django.contrib.sites is not installed." "django.contrib.sites is not installed."

View File

@ -1,6 +1,7 @@
from django import http from django import http
from django.conf import settings from django.conf import settings
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core.apps import app_cache
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
@ -56,12 +57,10 @@ class RedirectTests(TestCase):
response = self.client.get('/initial') response = self.client.get('/initial')
self.assertEqual(response.status_code, 410) self.assertEqual(response.status_code, 410)
@override_settings(
INSTALLED_APPS=[app for app in settings.INSTALLED_APPS
if app != 'django.contrib.sites'])
def test_sites_not_installed(self): def test_sites_not_installed(self):
with self.assertRaises(ImproperlyConfigured): with app_cache._without_app('django.contrib.sites'):
RedirectFallbackMiddleware() with self.assertRaises(ImproperlyConfigured):
RedirectFallbackMiddleware()
class OverriddenRedirectFallbackMiddleware(RedirectFallbackMiddleware): class OverriddenRedirectFallbackMiddleware(RedirectFallbackMiddleware):

View File

@ -3,13 +3,14 @@ from __future__ import unicode_literals
from unittest import skipUnless from unittest import skipUnless
from django.conf import settings from django.conf import settings
from django.core.apps import app_cache
from .base import SitemapTestsBase from .base import SitemapTestsBase
class FlatpagesSitemapTests(SitemapTestsBase): class FlatpagesSitemapTests(SitemapTestsBase):
@skipUnless("django.contrib.flatpages" in settings.INSTALLED_APPS, @skipUnless(app_cache.has_app('django.contrib.flatpages'),
"django.contrib.flatpages app not installed.") "django.contrib.flatpages app not installed.")
def test_flatpage_sitemap(self): def test_flatpage_sitemap(self):
"Basic FlatPage sitemap test" "Basic FlatPage sitemap test"

View File

@ -118,7 +118,7 @@ class HTTPSitemapTests(SitemapTestsBase):
""" % date.today() """ % date.today()
self.assertXMLEqual(response.content.decode('utf-8'), expected_content) self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
@skipUnless("django.contrib.sites" in settings.INSTALLED_APPS, @skipUnless(app_cache.has_app('django.contrib.sites'),
"django.contrib.sites app not installed.") "django.contrib.sites app not installed.")
def test_sitemap_get_urls_no_site_1(self): def test_sitemap_get_urls_no_site_1(self):
""" """

View File

@ -298,6 +298,18 @@ class AppCache(object):
models[model_name] = model models[model_name] = model
self._get_models_cache.clear() self._get_models_cache.clear()
def has_app(self, app_name):
"""
Returns the application config if one is registered and None otherwise.
It's safe to call this method at import time, even while the app cache
is being populated. It returns None for apps that aren't loaded yet.
"""
app_config = self.app_configs.get(app_name.rpartition(".")[2])
if app_config is not None and app_config.name != app_name:
app_config = None
return app_config
def has_model(self, app_label, model_name): def has_model(self, app_label, model_name):
""" """
Returns the model class if one is registered and None otherwise. Returns the model class if one is registered and None otherwise.

View File

@ -10,6 +10,7 @@ from io import BytesIO
from django.conf import settings from django.conf import settings
from django.contrib.auth import authenticate, login, logout, get_user_model from django.contrib.auth import authenticate, login, logout, get_user_model
from django.core.apps import app_cache
from django.core.handlers.base import BaseHandler from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import WSGIRequest from django.core.handlers.wsgi import WSGIRequest
from django.core.signals import (request_started, request_finished, from django.core.signals import (request_started, request_finished,
@ -389,7 +390,7 @@ class Client(RequestFactory):
""" """
Obtains the current session variables. Obtains the current session variables.
""" """
if 'django.contrib.sessions' in settings.INSTALLED_APPS: if app_cache.has_app('django.contrib.sessions'):
engine = import_module(settings.SESSION_ENGINE) engine = import_module(settings.SESSION_ENGINE)
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None) cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
if cookie: if cookie:
@ -550,7 +551,7 @@ class Client(RequestFactory):
""" """
user = authenticate(**credentials) user = authenticate(**credentials)
if (user and user.is_active and if (user and user.is_active and
'django.contrib.sessions' in settings.INSTALLED_APPS): app_cache.has_app('django.contrib.sessions')):
engine = import_module(settings.SESSION_ENGINE) engine = import_module(settings.SESSION_ENGINE)
# Create a fake request that goes through request middleware # Create a fake request that goes through request middleware

View File

@ -2,6 +2,7 @@ from django.conf import settings
from django.contrib import comments from django.contrib import comments
from django.contrib.comments.models import Comment from django.contrib.comments.models import Comment
from django.contrib.comments.forms import CommentForm from django.contrib.comments.forms import CommentForm
from django.core.apps import app_cache
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.test.utils import override_settings from django.test.utils import override_settings
from django.utils import six from django.utils import six
@ -15,14 +16,6 @@ class CommentAppAPITests(CommentTestCase):
def testGetCommentApp(self): def testGetCommentApp(self):
self.assertEqual(comments.get_comment_app(), comments) self.assertEqual(comments.get_comment_app(), comments)
@override_settings(
COMMENTS_APP='missing_app',
INSTALLED_APPS=list(settings.INSTALLED_APPS) + ['missing_app'],
)
def testGetMissingCommentApp(self):
with six.assertRaisesRegex(self, ImproperlyConfigured, 'missing_app'):
comments.get_comment_app()
def testGetForm(self): def testGetForm(self):
self.assertEqual(comments.get_form(), CommentForm) self.assertEqual(comments.get_form(), CommentForm)
@ -42,14 +35,16 @@ class CommentAppAPITests(CommentTestCase):
self.assertEqual(comments.get_approve_url(c), "/approve/12345/") self.assertEqual(comments.get_approve_url(c), "/approve/12345/")
@override_settings( @override_settings(COMMENTS_APP='comment_tests.custom_comments')
COMMENTS_APP='comment_tests.custom_comments',
INSTALLED_APPS=list(settings.INSTALLED_APPS) + [
'comment_tests.custom_comments'],
)
class CustomCommentTest(CommentTestCase): class CustomCommentTest(CommentTestCase):
urls = 'comment_tests.urls' urls = 'comment_tests.urls'
def setUp(self):
self._with_custom_comments = app_cache._begin_with_app('comment_tests.custom_comments')
def tearDown(self):
app_cache._end_with_app(self._with_custom_comments)
def testGetCommentApp(self): def testGetCommentApp(self):
from comment_tests import custom_comments from comment_tests import custom_comments
self.assertEqual(comments.get_comment_app(), custom_comments) self.assertEqual(comments.get_comment_app(), custom_comments)