Skip to content

Commit

Permalink
Stopped iterating on INSTALLED_APPS.
Browse files Browse the repository at this point in the history
Used the app cache's get_app_configs() method instead.
  • Loading branch information
aaugustin committed Dec 22, 2013
1 parent d4733b6 commit 65cd74b
Show file tree
Hide file tree
Showing 18 changed files with 116 additions and 82 deletions.
6 changes: 4 additions & 2 deletions django/contrib/staticfiles/finders.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os

from django.conf import settings
from django.core.apps import app_cache
from django.core.exceptions import ImproperlyConfigured
from django.core.files.storage import default_storage, Storage, FileSystemStorage
from django.utils.functional import empty, LazyObject
Expand Down Expand Up @@ -116,10 +117,11 @@ class AppDirectoriesFinder(BaseFinder):
def __init__(self, apps=None, *args, **kwargs):
# The list of apps that are handled
self.apps = []
# Mapping of app module paths to storage instances
# Mapping of app names to storage instances
self.storages = OrderedDict()
if apps is None:
apps = settings.INSTALLED_APPS
app_configs = app_cache.get_app_configs()
apps = [app_config.name for app_config in app_configs]
for app in apps:
app_storage = self.storage_class(app)
if os.path.isdir(app_storage.location):
Expand Down
20 changes: 14 additions & 6 deletions django/core/management/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import os
import sys

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand, CommandError, handle_default_options
from django.core.management.color import color_style
Expand Down Expand Up @@ -106,13 +107,19 @@ def get_commands():
_commands = dict((name, 'django.core') for name in find_commands(__path__[0]))

# Find the installed apps
from django.conf import settings
try:
apps = settings.INSTALLED_APPS
settings.INSTALLED_APPS
except ImproperlyConfigured:
# Still useful for commands that do not require functional settings,
# like startproject or help
# Still useful for commands that do not require functional
# settings, like startproject or help.
apps = []
else:
# Populate the app cache outside of the try/except block to avoid
# catching ImproperlyConfigured errors that aren't caused by the
# absence of a settings module.
from django.core.apps import app_cache
app_configs = app_cache.get_app_configs()
apps = [app_config.name for app_config in app_configs]

# Find and load the management module for each installed app.
for app_name in apps:
Expand Down Expand Up @@ -339,9 +346,10 @@ def autocomplete(self):
elif cwords[0] in ('dumpdata', 'sql', 'sqlall', 'sqlclear',
'sqlcustom', 'sqlindexes', 'sqlsequencereset', 'test'):
try:
from django.conf import settings
from django.core.apps import app_cache
app_configs = app_cache.get_app_configs()
# Get the last part of the dotted path as the app name.
options += [(a.split('.')[-1], 0) for a in settings.INSTALLED_APPS]
options += [(app_config.label, 0) for app_config in app_configs]
except ImportError:
# Fail silently if DJANGO_SETTINGS_MODULE isn't set. The
# user will find out once they execute the command.
Expand Down
5 changes: 2 additions & 3 deletions django/core/management/commands/flush.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from importlib import import_module
from optparse import make_option

from django.conf import settings
from django.core.apps import app_cache
from django.db import connections, router, transaction, DEFAULT_DB_ALIAS
from django.core.management import call_command
Expand Down Expand Up @@ -42,9 +41,9 @@ def handle_noargs(self, **options):

# Import the 'management' module within each installed app, to register
# dispatcher events.
for app_name in settings.INSTALLED_APPS:
for app_config in app_cache.get_app_configs():
try:
import_module('.management', app_name)
import_module('.management', app_config.name)
except ImportError:
pass

Expand Down
7 changes: 3 additions & 4 deletions django/core/management/commands/migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import itertools
import traceback

from django.conf import settings
from django.core.apps import app_cache
from django.core.management import call_command
from django.core.management.base import BaseCommand, CommandError
Expand Down Expand Up @@ -47,9 +46,9 @@ def handle(self, *args, **options):

# Import the 'management' module within each installed app, to register
# dispatcher events.
for app_name in settings.INSTALLED_APPS:
if module_has_submodule(import_module(app_name), "management"):
import_module('.management', app_name)
for app_config in app_cache.get_app_configs():
if module_has_submodule(app_config.app_module, "management"):
import_module('.management', app_config.name)

# Get the database we're operating from
db = options.get('database')
Expand Down
8 changes: 6 additions & 2 deletions django/template/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from inspect import getargspec, getcallargs

from django.conf import settings
from django.core.apps import app_cache
from django.template.context import (BaseContext, Context, RequestContext, # NOQA: imported for backwards compatibility
ContextPopException)
from django.utils.itercompat import is_iterable
Expand Down Expand Up @@ -1302,9 +1303,12 @@ def get_templatetags_modules():
# Populate list once per process. Mutate the local list first, and
# then assign it to the global name to ensure there are no cases where
# two threads try to populate it simultaneously.
for app_module in ['django'] + list(settings.INSTALLED_APPS):

templatetags_modules_candidates = ['django.templatetags']
templatetags_modules_candidates += ['%s.templatetags' % app_config.name
for app_config in app_cache.get_app_configs()]
for templatetag_module in templatetags_modules_candidates:
try:
templatetag_module = '%s.templatetags' % app_module
import_module(templatetag_module)
_templatetags_modules.append(templatetag_module)
except ImportError:
Expand Down
11 changes: 3 additions & 8 deletions django/template/loaders/app_directories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
packages.
"""

from importlib import import_module
import os
import sys

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.apps import app_cache
from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader
from django.utils._os import safe_join
Expand All @@ -18,12 +17,8 @@
if six.PY2:
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
app_template_dirs = []
for app in settings.INSTALLED_APPS:
try:
mod = import_module(app)
except ImportError as e:
raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
for app_config in app_cache.get_app_configs():
template_dir = os.path.join(app_config.path, 'templates')
if os.path.isdir(template_dir):
if six.PY2:
template_dir = template_dir.decode(fs_encoding)
Expand Down
7 changes: 4 additions & 3 deletions django/template/loaders/eggs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
resource_string = None

from django.conf import settings
from django.core.apps import app_cache
from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader
from django.utils import six
Expand All @@ -23,12 +24,12 @@ def load_template_source(self, template_name, template_dirs=None):
"""
if resource_string is not None:
pkg_name = 'templates/' + template_name
for app in settings.INSTALLED_APPS:
for app_config in app_cache.get_app_configs():
try:
resource = resource_string(app, pkg_name)
resource = resource_string(app_config.name, pkg_name)
except Exception:
continue
if six.PY2:
resource = resource.decode(settings.FILE_CHARSET)
return (resource, 'egg:%s:%s' % (app, pkg_name))
return (resource, 'egg:%s:%s' % (app_config.name, pkg_name))
raise TemplateDoesNotExist(template_name)
9 changes: 3 additions & 6 deletions django/utils/autoreload.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@
import traceback

from django.conf import settings
from django.core.apps import app_cache
from django.core.signals import request_finished
from django.utils._os import upath
from importlib import import_module
try:
from django.utils.six.moves import _thread as thread
except ImportError:
Expand Down Expand Up @@ -91,10 +90,8 @@ def gen_filenames():
basedirs = [os.path.join(os.path.dirname(os.path.dirname(__file__)),
'conf', 'locale'),
'locale']
for appname in reversed(settings.INSTALLED_APPS):
app = import_module(appname)
basedirs.append(os.path.join(os.path.dirname(upath(app.__file__)),
'locale'))
for app_config in reversed(list(app_cache.get_app_configs())):
basedirs.append(os.path.join(app_config.path, 'locale'))
basedirs.extend(settings.LOCALE_PATHS)
basedirs = [os.path.abspath(basedir) for basedir in basedirs
if os.path.isdir(basedir)]
Expand Down
9 changes: 4 additions & 5 deletions django/utils/module_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,17 @@ def autodiscover_modules(*args, **kwargs):
registry. This register_to object must have a _registry instance variable
to access it.
"""
from django.conf import settings
from django.core.apps import app_cache

register_to = kwargs.get('register_to')
for app in settings.INSTALLED_APPS:
mod = import_module(app)
for app_config in app_cache.get_app_configs():
# Attempt to import the app's module.
try:
if register_to:
before_import_registry = copy.copy(register_to._registry)

for module_to_search in args:
import_module('%s.%s' % (app, module_to_search))
import_module('%s.%s' % (app_config.name, module_to_search))
except:
# Reset the model registry to the state before the last import as
# this import will have to reoccur on the next request and this
Expand All @@ -81,7 +80,7 @@ def autodiscover_modules(*args, **kwargs):
# Decide whether to bubble up this error. If the app just
# doesn't have an admin module, we can ignore the error
# attempting to import it, otherwise we want it to bubble up.
if module_has_submodule(mod, module_to_search):
if module_has_submodule(app_config.app_module, module_to_search):
raise


Expand Down
8 changes: 3 additions & 5 deletions django/utils/translation/trans_real.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import re
import sys
import gettext as gettext_module
from importlib import import_module
from threading import local
import warnings

from django.core.apps import app_cache
from django.dispatch import receiver
from django.test.signals import setting_changed
from django.utils.encoding import force_str, force_text
Expand Down Expand Up @@ -179,10 +179,8 @@ def _merge(path):
res.merge(t)
return res

for appname in reversed(settings.INSTALLED_APPS):
app = import_module(appname)
apppath = os.path.join(os.path.dirname(upath(app.__file__)), 'locale')

for app_config in reversed(list(app_cache.get_app_configs())):
apppath = os.path.join(app_config.path, 'locale')
if os.path.isdir(apppath):
res = _merge(apppath)

Expand Down
6 changes: 5 additions & 1 deletion django/views/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from django import http
from django.conf import settings
from django.core.apps import app_cache
from django.template import Context, Template
from django.utils.translation import check_for_language, to_locale, get_language
from django.utils.encoding import smart_text
Expand Down Expand Up @@ -187,7 +188,10 @@ def render_javascript_catalog(catalog=None, plural=None):

def get_javascript_catalog(locale, domain, packages):
default_locale = to_locale(settings.LANGUAGE_CODE)
packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS]
app_configs = app_cache.get_app_configs()
allowable_packages = set(app_config.name for app_config in app_configs)
allowable_packages.add('django.conf')
packages = [p for p in packages if p in allowable_packages]
t = {}
paths = []
en_selected = locale.startswith('en')
Expand Down
8 changes: 5 additions & 3 deletions tests/bash_completion/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import sys
import unittest

from django.conf import settings
from django.core.apps import app_cache
from django.core.management import ManagementUtility
from django.utils.six import StringIO

Expand Down Expand Up @@ -84,5 +84,7 @@ def test_app_completion(self):
"Application names will be autocompleted for an AppCommand"
self._user_input('django-admin.py sqlall a')
output = self._run_autocomplete()
app_labels = [name.split('.')[-1] for name in settings.INSTALLED_APPS]
self.assertEqual(output, sorted(label for label in app_labels if label.startswith('a')))
a_labels = sorted(app_config.label
for app_config in app_cache.get_app_configs()
if app_config.label.startswith('a'))
self.assertEqual(output, a_labels)
26 changes: 22 additions & 4 deletions tests/i18n/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from threading import local

from django.conf import settings
from django.core.apps import app_cache
from django.template import Template, Context
from django.template.base import TemplateSyntaxError
from django.test import TestCase, RequestFactory
Expand Down Expand Up @@ -1035,11 +1036,29 @@ def assertUgettext(self, msgid, msgstr):
"translation of '%s'; the actual result is '%s'." % (msgstr, msgid, result)))


@override_settings(INSTALLED_APPS=['i18n.resolution'] + list(settings.INSTALLED_APPS))
class AppResolutionOrderI18NTests(ResolutionOrderI18NTests):

def test_app_translation(self):
self.assertUgettext('Date/time', 'APP')
# This test relies on an implementation detail, namely the fact that
# _with_app adds the app at the list. Adjust the test if this changes.

# Original translation.
self.assertUgettext('Date/time', 'Datum/Zeit')

# Different translation.
with app_cache._with_app('i18n.resolution'):
self.flush_caches()
activate('de')

# Doesn't work because it's added later in the list.
self.assertUgettext('Date/time', 'Datum/Zeit')

with app_cache._without_app('admin'):
self.flush_caches()
activate('de')

# Unless the original is removed from the list.
self.assertUgettext('Date/time', 'Datum/Zeit (APP)')


@override_settings(LOCALE_PATHS=extended_locale_paths)
Expand All @@ -1049,8 +1068,7 @@ def test_locale_paths_translation(self):
self.assertUgettext('Time', 'LOCALE_PATHS')

def test_locale_paths_override_app_translation(self):
extended_apps = list(settings.INSTALLED_APPS) + ['i18n.resolution']
with self.settings(INSTALLED_APPS=extended_apps):
with app_cache._with_app('i18n.resolution'):
self.assertUgettext('Time', 'LOCALE_PATHS')


Expand Down
3 changes: 3 additions & 0 deletions tests/staticfiles_tests/test_liveserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ def test_test_test(self):

class StaticLiveServerView(LiveServerBase):

# The test is going to access a static file stored in this application.
available_apps = ['staticfiles_tests.apps.test']

def urlopen(self, url):
return urlopen(self.live_server_url + url)

Expand Down

0 comments on commit 65cd74b

Please sign in to comment.