diff options
Diffstat (limited to 'django')
24 files changed, 97 insertions, 54 deletions
diff --git a/django/apps/base.py b/django/apps/base.py index ea28797108..2ae40e2454 100644 --- a/django/apps/base.py +++ b/django/apps/base.py @@ -61,13 +61,12 @@ class AppConfig(object): Factory that creates an app config from an entry in INSTALLED_APPS. """ try: - # If import_module succeeds, entry is a path to an app module. + # If import_module succeeds, entry is a path to an app module, + # which may specify an app config class with default_app_config. # Otherwise, entry is a path to an app config class or an error. module = import_module(entry) except ImportError: - # Avoid django.utils.module_loading.import_by_path because it - # masks errors -- it reraises ImportError as ImproperlyConfigured. mod_path, _, cls_name = entry.rpartition('.') # Raise the original exception when entry cannot be a path to an @@ -75,39 +74,51 @@ class AppConfig(object): if not mod_path: raise - mod = import_module(mod_path) + else: try: - cls = getattr(mod, cls_name) + # If this works, the app module specifies an app config class. + entry = module.default_app_config except AttributeError: - # Emulate the error that "from <mod_path> import <cls_name>" - # would raise when <mod_path> exists but not <cls_name>, with - # more context (Python just says "cannot import name ..."). - raise ImportError( - "cannot import name '%s' from '%s'" % (cls_name, mod_path)) + # Otherwise, it simply uses the default app config class. + return cls(entry, module) + else: + mod_path, _, cls_name = entry.rpartition('.') - # Check for obvious errors. (This check prevents duck typing, but - # it could be removed if it became a problem in practice.) - if not issubclass(cls, AppConfig): - raise ImproperlyConfigured( - "'%s' isn't a subclass of AppConfig." % entry) + # If we're reaching this point, we must load the app config class + # located at <mod_path>.<cls_name>. - # Obtain app name here rather than in AppClass.__init__ to keep - # all error checking for entries in INSTALLED_APPS in one place. - try: - app_name = cls.name - except AttributeError: - raise ImproperlyConfigured( - "'%s' must supply a name attribute." % entry) + # Avoid django.utils.module_loading.import_by_path because it + # masks errors -- it reraises ImportError as ImproperlyConfigured. + mod = import_module(mod_path) + try: + cls = getattr(mod, cls_name) + except AttributeError: + # Emulate the error that "from <mod_path> import <cls_name>" + # would raise when <mod_path> exists but not <cls_name>, with + # more context (Python just says "cannot import name ..."). + raise ImportError( + "cannot import name '%s' from '%s'" % (cls_name, mod_path)) - # Ensure app_name points to a valid module. - app_module = import_module(app_name) + # Check for obvious errors. (This check prevents duck typing, but + # it could be removed if it became a problem in practice.) + if not issubclass(cls, AppConfig): + raise ImproperlyConfigured( + "'%s' isn't a subclass of AppConfig." % entry) - # Entry is a path to an app config class. - return cls(app_name, app_module) + # Obtain app name here rather than in AppClass.__init__ to keep + # all error checking for entries in INSTALLED_APPS in one place. + try: + app_name = cls.name + except AttributeError: + raise ImproperlyConfigured( + "'%s' must supply a name attribute." % entry) + + # Ensure app_name points to a valid module. + app_module = import_module(app_name) + + # Entry is a path to an app config class. + return cls(app_name, app_module) - else: - # Entry is a path to an app module. - return cls(entry, module) def get_model(self, model_name): """ diff --git a/django/conf/project_template/project_name/settings.py b/django/conf/project_template/project_name/settings.py index 198a3e0d92..efe8091e81 100644 --- a/django/conf/project_template/project_name/settings.py +++ b/django/conf/project_template/project_name/settings.py @@ -30,7 +30,7 @@ ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = ( - 'django.contrib.admin.apps.AdminConfig', + 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', diff --git a/django/contrib/admin/__init__.py b/django/contrib/admin/__init__.py index 530badf1df..2218dfd23f 100644 --- a/django/contrib/admin/__init__.py +++ b/django/contrib/admin/__init__.py @@ -1,6 +1,5 @@ # ACTION_CHECKBOX_NAME is unused, but should stay since its import from here # has been referenced in documentation. -from django.contrib.admin.checks import check_admin_app from django.contrib.admin.decorators import register from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME from django.contrib.admin.options import ModelAdmin, HORIZONTAL, VERTICAL @@ -9,7 +8,6 @@ from django.contrib.admin.filters import (ListFilter, SimpleListFilter, FieldListFilter, BooleanFieldListFilter, RelatedFieldListFilter, ChoicesFieldListFilter, DateFieldListFilter, AllValuesFieldListFilter) from django.contrib.admin.sites import AdminSite, site -from django.core import checks from django.utils.module_loading import autodiscover_modules __all__ = [ @@ -24,4 +22,5 @@ __all__ = [ def autodiscover(): autodiscover_modules('admin', register_to=site) -checks.register('admin')(check_admin_app) + +default_app_config = 'django.contrib.admin.apps.AdminConfig' diff --git a/django/contrib/admin/apps.py b/django/contrib/admin/apps.py index a8f0e91ea6..93dab8a787 100644 --- a/django/contrib/admin/apps.py +++ b/django/contrib/admin/apps.py @@ -1,11 +1,22 @@ from django.apps import AppConfig - +from django.core import checks +from django.contrib.admin.checks import check_admin_app from django.utils.translation import ugettext_lazy as _ -class AdminConfig(AppConfig): +class SimpleAdminConfig(AppConfig): + """Simple AppConfig which does not do automatic discovery.""" + name = 'django.contrib.admin' verbose_name = _("administration") def ready(self): + checks.register('admin')(check_admin_app) + + +class AdminConfig(SimpleAdminConfig): + """The default AppConfig for admin which does autodiscovery.""" + + def ready(self): + super(AdminConfig, self).ready() self.module.autodiscover() diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index ba7c38dcad..f25055baf7 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -161,7 +161,7 @@ class AdminSite(object): installed, as well as the auth context processor. """ if not apps.is_installed('django.contrib.admin'): - raise ImproperlyConfigured("Put 'django.contrib.admin.apps.AdminConfig' in " + raise ImproperlyConfigured("Put 'django.contrib.admin' in " "your INSTALLED_APPS setting in order to use the admin application.") if not apps.is_installed('django.contrib.contenttypes'): raise ImproperlyConfigured("Put 'django.contrib.contenttypes' in " diff --git a/django/contrib/admindocs/__init__.py b/django/contrib/admindocs/__init__.py index e69de29bb2..733519ac54 100644 --- a/django/contrib/admindocs/__init__.py +++ b/django/contrib/admindocs/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.admindocs.apps.AdminDocsConfig' diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index 24c870dafe..77b2482e31 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -2,8 +2,6 @@ import inspect import re from django.conf import settings -from django.contrib.auth.checks import check_user_model -from django.core import checks from django.core.exceptions import ImproperlyConfigured, PermissionDenied from django.utils.module_loading import import_by_path from django.middleware.csrf import rotate_token @@ -15,10 +13,6 @@ BACKEND_SESSION_KEY = '_auth_user_backend' REDIRECT_FIELD_NAME = 'next' -# Register the user model checks -checks.register('models')(check_user_model) - - def load_backend(path): return import_by_path(path)() @@ -164,3 +158,6 @@ def get_permission_codename(action, opts): Returns the codename of the permission for the specified action. """ return '%s_%s' % (action, opts.model_name) + + +default_app_config = 'django.contrib.auth.apps.AuthConfig' diff --git a/django/contrib/auth/apps.py b/django/contrib/auth/apps.py index e44ad1a0c7..a0389acabe 100644 --- a/django/contrib/auth/apps.py +++ b/django/contrib/auth/apps.py @@ -1,4 +1,6 @@ from django.apps import AppConfig +from django.core import checks +from django.contrib.auth.checks import check_user_model from django.utils.translation import ugettext_lazy as _ @@ -6,3 +8,6 @@ from django.utils.translation import ugettext_lazy as _ class AuthConfig(AppConfig): name = 'django.contrib.auth' verbose_name = _("authentication and authorization") + + def ready(self): + checks.register('models')(check_user_model) diff --git a/django/contrib/comments/__init__.py b/django/contrib/comments/__init__.py index 19dd7ef9a1..a62fff1b56 100644 --- a/django/contrib/comments/__init__.py +++ b/django/contrib/comments/__init__.py @@ -1,6 +1,6 @@ from importlib import import_module import warnings -from django.apps import apps +from django.apps import apps as django_apps from django.conf import settings from django.core import urlresolvers from django.core.exceptions import ImproperlyConfigured @@ -16,7 +16,7 @@ def get_comment_app(): Get the comment app (i.e. "django.contrib.comments") as defined in the settings """ try: - app_config = apps.get_app_config(get_comment_app_name().rpartition(".")[2]) + app_config = django_apps.get_app_config(get_comment_app_name().rpartition(".")[2]) except LookupError: raise ImproperlyConfigured("The COMMENTS_APP (%r) " "must be in INSTALLED_APPS" % settings.COMMENTS_APP) @@ -85,3 +85,6 @@ def get_approve_url(comment): else: return urlresolvers.reverse("django.contrib.comments.views.moderation.approve", args=(comment.id,)) + + +default_app_config = 'django.contrib.comments.apps.CommentsConfig' diff --git a/django/contrib/contenttypes/__init__.py b/django/contrib/contenttypes/__init__.py index 5a04849f06..9789f36eff 100644 --- a/django/contrib/contenttypes/__init__.py +++ b/django/contrib/contenttypes/__init__.py @@ -1,8 +1 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib.contenttypes.checks import check_generic_foreign_keys -from django.core import checks - - -checks.register('models')(check_generic_foreign_keys) +default_app_config = 'django.contrib.contenttypes.apps.ContentTypesConfig' diff --git a/django/contrib/contenttypes/apps.py b/django/contrib/contenttypes/apps.py index 0e55e8d66d..4e515d8a00 100644 --- a/django/contrib/contenttypes/apps.py +++ b/django/contrib/contenttypes/apps.py @@ -1,8 +1,12 @@ from django.apps import AppConfig - +from django.contrib.contenttypes.checks import check_generic_foreign_keys +from django.core import checks from django.utils.translation import ugettext_lazy as _ class ContentTypesConfig(AppConfig): name = 'django.contrib.contenttypes' verbose_name = _("content types") + + def ready(self): + checks.register('models')(check_generic_foreign_keys) diff --git a/django/contrib/flatpages/__init__.py b/django/contrib/flatpages/__init__.py index e69de29bb2..865acd855b 100644 --- a/django/contrib/flatpages/__init__.py +++ b/django/contrib/flatpages/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.flatpages.apps.FlatPagesConfig' diff --git a/django/contrib/formtools/__init__.py b/django/contrib/formtools/__init__.py index e69de29bb2..b82588d8e7 100644 --- a/django/contrib/formtools/__init__.py +++ b/django/contrib/formtools/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.formtools.apps.FormToolsConfig' diff --git a/django/contrib/gis/__init__.py b/django/contrib/gis/__init__.py index c996fdfdc2..84b3552ce7 100644 --- a/django/contrib/gis/__init__.py +++ b/django/contrib/gis/__init__.py @@ -4,3 +4,6 @@ if six.PY3: memoryview = memoryview else: memoryview = buffer + + +default_app_config = 'django.contrib.gis.apps.GISConfig' diff --git a/django/contrib/humanize/__init__.py b/django/contrib/humanize/__init__.py index e69de29bb2..9ca1642fae 100644 --- a/django/contrib/humanize/__init__.py +++ b/django/contrib/humanize/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.humanize.apps.HumanizeConfig' diff --git a/django/contrib/messages/__init__.py b/django/contrib/messages/__init__.py index 40ba6ea6c7..a0cb24b2d9 100644 --- a/django/contrib/messages/__init__.py +++ b/django/contrib/messages/__init__.py @@ -1,2 +1,5 @@ from django.contrib.messages.api import * # NOQA from django.contrib.messages.constants import * # NOQA + + +default_app_config = 'django.contrib.messages.apps.MessagesConfig' diff --git a/django/contrib/redirects/__init__.py b/django/contrib/redirects/__init__.py index e69de29bb2..65364a440b 100644 --- a/django/contrib/redirects/__init__.py +++ b/django/contrib/redirects/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.redirects.apps.RedirectsConfig' diff --git a/django/contrib/sessions/__init__.py b/django/contrib/sessions/__init__.py index e69de29bb2..0382f95d7e 100644 --- a/django/contrib/sessions/__init__.py +++ b/django/contrib/sessions/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.sessions.apps.SessionsConfig' diff --git a/django/contrib/sitemaps/__init__.py b/django/contrib/sitemaps/__init__.py index 4396708098..ee3d22090d 100644 --- a/django/contrib/sitemaps/__init__.py +++ b/django/contrib/sitemaps/__init__.py @@ -133,3 +133,6 @@ class GenericSitemap(Sitemap): if self.date_field is not None: return getattr(item, self.date_field) return None + + +default_app_config = 'django.contrib.sitemaps.apps.SiteMapsConfig' diff --git a/django/contrib/sites/__init__.py b/django/contrib/sites/__init__.py index e69de29bb2..b554240bb2 100644 --- a/django/contrib/sites/__init__.py +++ b/django/contrib/sites/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.sites.apps.SitesConfig' diff --git a/django/contrib/staticfiles/__init__.py b/django/contrib/staticfiles/__init__.py index e69de29bb2..8a07b83d2f 100644 --- a/django/contrib/staticfiles/__init__.py +++ b/django/contrib/staticfiles/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.staticfiles.apps.StaticFilesConfig' diff --git a/django/contrib/syndication/__init__.py b/django/contrib/syndication/__init__.py index e69de29bb2..2c3f52578d 100644 --- a/django/contrib/syndication/__init__.py +++ b/django/contrib/syndication/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.syndication.apps.SyndicationConfig' diff --git a/django/contrib/webdesign/__init__.py b/django/contrib/webdesign/__init__.py index e69de29bb2..2340116bc8 100644 --- a/django/contrib/webdesign/__init__.py +++ b/django/contrib/webdesign/__init__.py @@ -0,0 +1 @@ +default_app_config = 'django.contrib.webdesign.apps.WebDesignConfig' diff --git a/django/core/checks/registry.py b/django/core/checks/registry.py index efb5b4b892..21efbf317e 100644 --- a/django/core/checks/registry.py +++ b/django/core/checks/registry.py @@ -29,7 +29,8 @@ class CheckRegistry(object): def inner(check): check.tags = tags - self.registered_checks.append(check) + if check not in self.registered_checks: + self.registered_checks.append(check) return check return inner |
