Ticket #3591: app-loading.diff

File app-loading.diff, 100.8 KB (added by Jannis Leidel, 13 years ago)

correct patch

  • new file django/apps/__init__.py

    diff --git a/django/apps/__init__.py b/django/apps/__init__.py
    new file mode 100644
    index 0000000..ca60d0c
    - +  
     1from django.apps.base import App
     2from django.apps.cache import AppCache
     3
     4__all__ = (
     5    'App', 'find_app', 'get_apps', 'get_app', 'get_app_errors',
     6    'get_models', 'get_model', 'register_models', 'load_app',
     7    'app_cache_ready'
     8)
     9
     10cache = AppCache()
     11
     12# These methods were always module level, so are kept that way for backwards
     13# compatibility.
     14find_app = cache.find_app
     15get_apps = cache.get_apps
     16get_app = cache.get_app
     17get_app_errors = cache.get_app_errors
     18get_models = cache.get_models
     19get_model = cache.get_model
     20register_models = cache.register_models
     21load_app = cache.load_app
     22app_cache_ready = cache.app_cache_ready
  • new file django/apps/base.py

    diff --git a/django/apps/base.py b/django/apps/base.py
    new file mode 100644
    index 0000000..21990bb
    - +  
     1import re
     2import sys
     3
     4from django.apps.options import AppOptions, DEFAULT_NAMES
     5
     6module_name_re = re.compile(r'_([a-z])')
     7
     8
     9class AppBase(type):
     10    """
     11    Metaclass for all apps.
     12    """
     13    def __new__(cls, name, bases, attrs):
     14        super_new = super(AppBase, cls).__new__
     15        parents = [b for b in bases if isinstance(b, AppBase)]
     16        if not parents:
     17            # If this isn't a subclass of App, don't do anything special.
     18            return super_new(cls, name, bases, attrs)
     19        module = attrs.pop('__module__', None)
     20        new_class = super_new(cls, name, bases, {'__module__': module})
     21        attr_meta = attrs.pop('Meta', None)
     22        if not attr_meta:
     23            meta = getattr(new_class, 'Meta', None)
     24        else:
     25            meta = attr_meta
     26        app_name = attrs.pop('_name', None)
     27        if app_name is None:
     28            # Figure out the app_name by looking one level up.
     29            # For 'django.contrib.sites.app', this would be 'django.contrib.sites'
     30            app_module = sys.modules[new_class.__module__]
     31            app_name = app_module.__name__.rsplit('.', 1)[0]
     32        new_class.add_to_class('_meta', AppOptions(app_name, meta))
     33        # For easier Meta inheritance
     34        new_class.add_to_class('Meta', attr_meta)
     35        return new_class
     36
     37    def add_to_class(cls, name, value):
     38        if hasattr(value, 'contribute_to_class'):
     39            value.contribute_to_class(cls, name)
     40        else:
     41            setattr(cls, name, value)
     42
     43
     44class App(object):
     45    """
     46    The base app class to be subclassed for own uses.
     47    """
     48    __metaclass__ = AppBase
     49
     50    def __init__(self, **options):
     51        for key, value in options.iteritems():
     52            if key in DEFAULT_NAMES:
     53                setattr(self._meta, key, value)
     54            else:
     55                setattr(self, key, value)
     56
     57    def __repr__(self):
     58        return '<App: %s>' % self._meta.name
     59
     60    @classmethod
     61    def from_name(cls, name):
     62        upper = lambda match: match.group(1).upper()
     63        cls_name = module_name_re.sub(upper, name.split('.')[-1])
     64        return type(cls_name[0].upper()+cls_name[1:], (cls,), {'_name': name})
  • new file django/apps/cache.py

    diff --git a/django/apps/cache.py b/django/apps/cache.py
    new file mode 100644
    index 0000000..4973e74
    - +  
     1import sys
     2import os
     3import threading
     4
     5from django.conf import settings
     6from django.core.exceptions import ImproperlyConfigured
     7from django.utils.datastructures import SortedDict
     8from django.utils.importlib import import_module
     9from django.utils.module_loading import module_has_submodule
     10
     11from django.apps.base import App
     12from django.apps.signals import app_loaded, post_apps_loaded
     13
     14
     15def _initialize():
     16    """
     17    Returns a dictionary to be used as the initial value of the
     18    shared state of the app cache.
     19    """
     20    return {
     21        # list of loaded app instances
     22        'loaded_apps': [],
     23
     24        # Mapping of app_labels to a dictionary of model names to model code.
     25        'app_models': SortedDict(),
     26
     27        # -- Everything below here is only used when populating the cache --
     28        'loaded': False,
     29        'handled': [],
     30        'postponed': [],
     31        'nesting_level': 0,
     32        '_get_models_cache': {},
     33    }
     34
     35
     36class AppCache(object):
     37    """
     38    A cache that stores installed applications and their models. Used to
     39    provide reverse-relations and for app introspection (e.g. admin).
     40    """
     41    # Use the Borg pattern to share state between all instances. Details at
     42    # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531.
     43    __shared_state = dict(_initialize(), write_lock=threading.RLock())
     44
     45    def __init__(self):
     46        self.__dict__ = self.__shared_state
     47
     48    def _reset(self):
     49        """
     50        Resets the cache to its initial (unseeded) state
     51        """
     52        # remove imported model modules, so ModelBase.__new__ can register
     53        # them with the cache again
     54        for app, models in self.app_models.iteritems():
     55            for model in models.itervalues():
     56                module = model.__module__
     57                if module in sys.modules:
     58                    del sys.modules[module]
     59        self.__class__.__shared_state.update(_initialize())
     60
     61    def _reload(self):
     62        """
     63        Reloads the cache
     64        """
     65        self._reset()
     66        self._populate()
     67
     68    def _populate(self):
     69        """
     70        Fill in all the cache information. This method is threadsafe, in the
     71        sense that every caller will see the same state upon return, and if the
     72        cache is already initialised, it does no work.
     73        """
     74        if self.loaded:
     75            return
     76        self.write_lock.acquire()
     77        try:
     78            if self.loaded:
     79                return
     80            for app_name in settings.INSTALLED_APPS:
     81                if isinstance(app_name, (tuple, list)):
     82                    app_name, app_kwargs = app_name
     83                else:
     84                    app_kwargs = {}
     85                if app_name in self.handled:
     86                    continue
     87                self.load_app(app_name, app_kwargs, True)
     88            if not self.nesting_level:
     89                for app_name, app_kwargs in self.postponed:
     90                    self.load_app(app_name, app_kwargs)
     91                # assign models to app instances
     92                for app in self.loaded_apps:
     93                    parents = [p for p in app.__class__.mro()
     94                               if hasattr(p, '_meta')]
     95                    for parent in reversed(parents):
     96                        parent_models = self.app_models.get(parent._meta.label, {})
     97                        # update app_label and installed attribute of parent models
     98                        for model in parent_models.itervalues():
     99                            model._meta.app_label = app._meta.label
     100                            model._meta.installed = True
     101                        app._meta.models.update(parent_models)
     102
     103                # check if there is more than one app with the same
     104                # db_prefix attribute
     105                for app1 in self.loaded_apps:
     106                    for app2 in self.loaded_apps:
     107                        if (app1 != app2 and
     108                                app1._meta.db_prefix == app2._meta.db_prefix):
     109                            raise ImproperlyConfigured(
     110                                'The apps "%s" and "%s" have the same db_prefix "%s"'
     111                                % (app1, app2, app1._meta.db_prefix))
     112                self.loaded = True
     113                # send the post_apps_loaded signal
     114                post_apps_loaded.send(sender=self, apps=self.loaded_apps)
     115        finally:
     116            self.write_lock.release()
     117
     118    def get_app_class(self, app_name):
     119        """
     120        Returns an app class for the given app name, which can be a
     121        dotted path to an app class or a dotted app module path.
     122        """
     123        try:
     124            app_path, app_attr = app_name.rsplit('.', 1)
     125        except ValueError:
     126            # First, return a new app class for the given module if
     127            # it's one level module path that can't be rsplit (e.g. 'myapp')
     128            return App.from_name(app_name)
     129        try:
     130            # Secondly, try to import the module directly,
     131            # because it'll fail with a class path or a bad path
     132            app_module = import_module(app_path)
     133        except ImportError, e:
     134            raise ImproperlyConfigured(
     135                "Could not import app '%s': %s" % (app_path, e))
     136        else:
     137            # Thirdly, check if there is the submodule and fall back if yes
     138            # If not look for the app class and do some type checks
     139            if not module_has_submodule(app_module, app_attr):
     140                try:
     141                    app_class = getattr(app_module, app_attr)
     142                except AttributeError:
     143                    raise ImproperlyConfigured(
     144                        "Could not find app '%s' in "
     145                        "module '%s'" % (app_attr, app_path))
     146                else:
     147                    if not issubclass(app_class, App):
     148                        raise ImproperlyConfigured(
     149                            "App '%s' must be a subclass of "
     150                            "'django.apps.App'" % app_name)
     151                    return app_class
     152        return App.from_name(app_name)
     153
     154    def load_app(self, app_name, app_kwargs=None, can_postpone=False):
     155        """
     156        Loads the app with the provided fully qualified name, and returns the
     157        model module.
     158
     159        Keyword Arguments:
     160            app_name: fully qualified name (e.g. 'django.contrib.auth')
     161            can_postpone: If set to True and the import raises an ImportError
     162                the loading will be postponed and tried again when all other
     163                modules are loaded.
     164        """
     165        if app_kwargs is None:
     166            app_kwargs = {}
     167
     168        self.handled.append(app_name)
     169        self.nesting_level += 1
     170
     171        # check if an app instance with app_name already exists, if not
     172        # then create one
     173        app = self.find_app(app_name.split('.')[-1])
     174        if not app:
     175            app_class = self.get_app_class(app_name)
     176            app = app_class(**app_kwargs)
     177            self.loaded_apps.append(app)
     178            # Send the signal that the app has been loaded
     179            app_loaded.send(sender=app_class, app=app)
     180
     181        # import the app's models module and handle ImportErrors
     182        try:
     183            models = import_module(app._meta.models_path)
     184        except ImportError:
     185            self.nesting_level -= 1
     186            # If the app doesn't have a models module, we can just ignore the
     187            # ImportError and return no models for it.
     188            if not module_has_submodule(app._meta.module, 'models'):
     189                return None
     190            # But if the app does have a models module, we need to figure out
     191            # whether to suppress or propagate the error. If can_postpone is
     192            # True then it may be that the package is still being imported by
     193            # Python and the models module isn't available yet. So we add the
     194            # app to the postponed list and we'll try it again after all the
     195            # recursion has finished (in populate). If can_postpone is False
     196            # then it's time to raise the ImportError.
     197            else:
     198                if can_postpone:
     199                    self.postponed.append((app_name, app_kwargs))
     200                    return None
     201                else:
     202                    raise
     203
     204        self.nesting_level -= 1
     205        app._meta.models_module = models
     206        return models
     207
     208    def find_app(self, app_label):
     209        """
     210        Returns the app instance that matches the given label.
     211        """
     212        for app in self.loaded_apps:
     213            if app._meta.label == app_label:
     214                return app
     215
     216    def find_app_by_models_module(self, models_module):
     217        """
     218        Returns the app instance that matches the models module
     219        """
     220        for app in self.loaded_apps:
     221            if app._meta.models_module == models_module:
     222                return app
     223
     224    def app_cache_ready(self):
     225        """
     226        Returns true if the model cache is fully populated.
     227
     228        Useful for code that wants to cache the results of get_models() for
     229        themselves once it is safe to do so.
     230        """
     231        return self.loaded
     232
     233    def get_apps(self):
     234        """
     235        Returns a list of all models modules.
     236        """
     237        self._populate()
     238        return [app._meta.models_module for app in self.loaded_apps
     239                if app._meta.models_module]
     240
     241    def get_app(self, app_label, emptyOK=False):
     242        """
     243        Returns the module containing the models for the given app_label. If
     244        the app has no models in it and 'emptyOK' is True, returns None.
     245        """
     246        self._populate()
     247        app = self.find_app(app_label)
     248        if app:
     249            mod = app._meta.models_module
     250            if mod is None:
     251                if emptyOK:
     252                    return None
     253            else:
     254                return mod
     255        raise ImproperlyConfigured(
     256                "App with label %s could not be found" % app_label)
     257
     258    def get_app_errors(self):
     259        """
     260        Returns the map of known problems with the INSTALLED_APPS.
     261        """
     262        self._populate()
     263        errors = {}
     264        for app in self.loaded_apps:
     265            if app._meta.errors:
     266                errors.update({app._meta.label: app._meta.errors})
     267        return errors
     268
     269    def get_models(self, app_mod=None,
     270                   include_auto_created=False, include_deferred=False,
     271                   only_installed=True):
     272        """
     273        Given a module containing models, returns a list of the models.
     274        Otherwise returns a list of all installed models.
     275
     276        By default, auto-created models (i.e., m2m models without an
     277        explicit intermediate table) are not included. However, if you
     278        specify include_auto_created=True, they will be.
     279
     280        By default, models created to satisfy deferred attribute
     281        queries are *not* included in the list of models. However, if
     282        you specify include_deferred, they will be.
     283        """
     284        cache_key = (app_mod, include_auto_created, include_deferred,
     285                     only_installed)
     286        try:
     287            return self._get_models_cache[cache_key]
     288        except KeyError:
     289            pass
     290        self._populate()
     291        app_list = []
     292        if app_mod and only_installed:
     293            app_label = app_mod.__name__.split('.')[-2]
     294            app = self.find_app(app_label)
     295            if app:
     296                app_list = [app._meta.models]
     297        else:
     298            if only_installed:
     299                app_list = [app._meta.models for app in self.loaded_apps]
     300            else:
     301                app_list = self.app_models.itervalues()
     302        model_list = []
     303        for app in app_list:
     304            model_list.extend(
     305                model for model in app.values()
     306                if ((not model._deferred or include_deferred) and
     307                    (not model._meta.auto_created or include_auto_created))
     308            )
     309        self._get_models_cache[cache_key] = model_list
     310        return model_list
     311
     312    def get_model(self, app_label, model_name,
     313                  seed_cache=True, only_installed=True):
     314        """
     315        Returns the model matching the given app_label and case-insensitive
     316        model_name.
     317
     318        Returns None if no model is found.
     319        """
     320        if seed_cache:
     321            self._populate()
     322        if only_installed:
     323            app = self.find_app(app_label)
     324            if not app:
     325                return
     326            return app._meta.models.get(model_name.lower())
     327        return self.app_models.get(app_label, SortedDict()).get(model_name.lower())
     328
     329    def register_models(self, app_label, *models):
     330        """
     331        Register a set of models as belonging to an app.
     332        """
     333        app = self.find_app(app_label)
     334        for model in models:
     335            model_name = model._meta.object_name.lower()
     336            model_dict = self.app_models.setdefault(app_label, SortedDict())
     337            if model_name in model_dict:
     338                # The same model may be imported via different paths (e.g.
     339                # appname.models and project.appname.models). We use the source
     340                # filename as a means to detect identity.
     341                fname1 = os.path.abspath(sys.modules[model.__module__].__file__)
     342                fname2 = os.path.abspath(sys.modules[model_dict[model_name].__module__].__file__)
     343                # Since the filename extension could be .py the first time and
     344                # .pyc or .pyo the second time, ignore the extension when
     345                # comparing.
     346                if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]:
     347                    continue
     348            if app:
     349                app._meta.models[model_name] = model
     350            model_dict[model_name] = model
     351        self._get_models_cache.clear()
  • new file django/apps/options.py

    diff --git a/django/apps/options.py b/django/apps/options.py
    new file mode 100644
    index 0000000..7a71552
    - +  
     1import re
     2import os
     3
     4from django.utils.datastructures import SortedDict
     5from django.utils.importlib import import_module
     6from django.utils.text import get_verbose_name
     7
     8DEFAULT_NAMES = ('verbose_name', 'db_prefix', 'models_path')
     9
     10
     11class AppOptions(object):
     12    def __init__(self, name, meta):
     13        self.name = name
     14        self.meta = meta
     15        self.errors = []
     16        self.models = SortedDict()
     17
     18    def contribute_to_class(self, cls, name):
     19        cls._meta = self
     20        # get the name from the path e.g. "auth" for "django.contrib.auth"
     21        self.label = self.name.split('.')[-1]
     22        self.models_module = None
     23        self.module = import_module(self.name)
     24        self.path = os.path.dirname(self.module.__file__)
     25        defaults = {
     26            'db_prefix': self.label,
     27            'models_path': '%s.models' % self.name,
     28            'verbose_name': get_verbose_name(self.label),
     29        }
     30        # Next, apply any overridden values from 'class Meta'.
     31        if self.meta:
     32            meta_attrs = self.meta.__dict__.copy()
     33            for name in self.meta.__dict__:
     34                # Ignore any private attributes that Django doesn't care about.
     35                if name.startswith('_'):
     36                    del meta_attrs[name]
     37            for attr_name in DEFAULT_NAMES:
     38                if attr_name in meta_attrs:
     39                    setattr(self, attr_name, meta_attrs.pop(attr_name))
     40                elif hasattr(self.meta, attr_name):
     41                    setattr(self, attr_name, getattr(self.meta, attr_name))
     42            # Any leftover attributes must be invalid.
     43            if meta_attrs != {}:
     44                raise TypeError("'class Meta' got invalid attribute(s): %s"
     45                                % ','.join(meta_attrs.keys()))
     46        del self.meta
     47
     48        for k, v in defaults.iteritems():
     49            if not hasattr(self, k):
     50                setattr(self, k, v)
  • new file django/apps/signals.py

    diff --git a/django/apps/signals.py b/django/apps/signals.py
    new file mode 100644
    index 0000000..befb77c
    - +  
     1from django.dispatch import Signal
     2
     3# Sent when an app is loaded by the app cache
     4app_loaded = Signal(providing_args=["app"])
     5
     6# Sent when the app cache loads the apps
     7post_apps_loaded = Signal(providing_args=["apps"])
  • django/contrib/admin/__init__.py

    diff --git a/django/contrib/admin/__init__.py b/django/contrib/admin/__init__.py
    index 1084784..0507223 100644
    a b  
    11# ACTION_CHECKBOX_NAME is unused, but should stay since its import from here
    22# has been referenced in documentation.
     3from django.apps import cache
    34from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
    45from django.contrib.admin.options import ModelAdmin, HORIZONTAL, VERTICAL
    56from django.contrib.admin.options import StackedInline, TabularInline
    from django.contrib.admin.filters import (ListFilter, SimpleListFilter,  
    89    FieldListFilter, BooleanFieldListFilter, RelatedFieldListFilter,
    910    ChoicesFieldListFilter, DateFieldListFilter, AllValuesFieldListFilter)
    1011
    11 
    1212def autodiscover():
    1313    """
    1414    Auto-discover INSTALLED_APPS admin.py modules and fail silently when
    def autodiscover():  
    2121    from django.utils.importlib import import_module
    2222    from django.utils.module_loading import module_has_submodule
    2323
    24     for app in settings.INSTALLED_APPS:
    25         mod = import_module(app)
     24    for app in cache.loaded_apps:
    2625        # Attempt to import the app's admin module.
    2726        try:
    2827            before_import_registry = copy.copy(site._registry)
    29             import_module('%s.admin' % app)
     28            import_module('%s.admin' % app._meta.name)
    3029        except:
    3130            # Reset the model registry to the state before the last import as
    3231            # this import will have to reoccur on the next request and this
    def autodiscover():  
    3736            # Decide whether to bubble up this error. If the app just
    3837            # doesn't have an admin module, we can ignore the error
    3938            # attempting to import it, otherwise we want it to bubble up.
    40             if module_has_submodule(mod, 'admin'):
     39            if module_has_submodule(app._meta.module, 'admin'):
    4140                raise
  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index cf7ea83..6a0f5dd 100644
    a b  
    11from functools import update_wrapper, partial
    2 from django import forms
     2from django import apps, forms, template
    33from django.forms.formsets import all_valid
    44from django.forms.models import (modelform_factory, modelformset_factory,
    55    inlineformset_factory, BaseInlineFormSet)
    class ModelAdmin(BaseModelAdmin):  
    968968            'media': mark_safe(media),
    969969            'inline_admin_formsets': inline_admin_formsets,
    970970            'errors': helpers.AdminErrorList(form, formsets),
    971             'app_label': opts.app_label,
     971            'app_label': apps.find_app(opts.app_label)._meta.verbose_name,
    972972        }
    973973        context.update(extra_context or {})
    974974        return self.render_change_form(request, context, form_url=form_url, add=True)
    class ModelAdmin(BaseModelAdmin):  
    10581058            'media': mark_safe(media),
    10591059            'inline_admin_formsets': inline_admin_formsets,
    10601060            'errors': helpers.AdminErrorList(form, formsets),
    1061             'app_label': opts.app_label,
     1061            'app_label': apps.find_app(opts.app_label)._meta.verbose_name,
    10621062        }
    10631063        context.update(extra_context or {})
    10641064        return self.render_change_form(request, context, change=True, obj=obj)
    class ModelAdmin(BaseModelAdmin):  
    11991199            'cl': cl,
    12001200            'media': media,
    12011201            'has_add_permission': self.has_add_permission(request),
    1202             'app_label': app_label,
     1202            'app_label': apps.find_app(app_label)._meta.verbose_name,
    12031203            'action_form': action_form,
    12041204            'actions_on_top': self.actions_on_top,
    12051205            'actions_on_bottom': self.actions_on_bottom,
    class ModelAdmin(BaseModelAdmin):  
    12631263            "perms_lacking": perms_needed,
    12641264            "protected": protected,
    12651265            "opts": opts,
    1266             "app_label": app_label,
     1266            "app_label": apps.find_app(app_label)._meta.verbose_name,
    12671267        }
    12681268        context.update(extra_context or {})
    12691269
    class ModelAdmin(BaseModelAdmin):  
    12901290            'action_list': action_list,
    12911291            'module_name': capfirst(force_unicode(opts.verbose_name_plural)),
    12921292            'object': obj,
    1293             'app_label': app_label,
     1293            'app_label': apps.find_app(app_label)._meta.verbose_name,
    12941294        }
    12951295        context.update(extra_context or {})
    12961296        return TemplateResponse(request, self.object_history_template or [
  • django/contrib/admin/sites.py

    diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
    index 49c1e78..92b4478 100644
    a b  
    11from functools import update_wrapper
    2 from django import http
     2
     3from django import apps, http
    34from django.contrib.admin import ModelAdmin, actions
    45from django.contrib.admin.forms import AdminAuthenticationForm
    56from django.contrib.auth import REDIRECT_FIELD_NAME
    class AdminSite(object):  
    348349                        app_dict[app_label]['models'].append(model_dict)
    349350                    else:
    350351                        app_dict[app_label] = {
    351                             'name': app_label.title(),
     352                            'name': apps.find_app(app_label)._meta.verbose_name,
    352353                            'app_url': app_label + '/',
    353354                            'has_module_perms': has_module_perms,
    354355                            'models': [model_dict],
    class AdminSite(object):  
    375376        user = request.user
    376377        has_module_perms = user.has_module_perms(app_label)
    377378        app_dict = {}
     379        app = apps.find_app(app_label)
    378380        for model, model_admin in self._registry.items():
    379381            if app_label == model._meta.app_label:
    380382                if has_module_perms:
    class AdminSite(object):  
    395397                            # something to display, add in the necessary meta
    396398                            # information.
    397399                            app_dict = {
    398                                 'name': app_label.title(),
     400                                'name': app._meta.verbose_name,
    399401                                'app_url': '',
    400402                                'has_module_perms': has_module_perms,
    401403                                'models': [model_dict],
    class AdminSite(object):  
    405407        # Sort the models alphabetically within each app.
    406408        app_dict['models'].sort(key=lambda x: x['name'])
    407409        context = {
    408             'title': _('%s administration') % capfirst(app_label),
     410            'title': _('%s administration') % app._meta.verbose_name,
    409411            'app_list': [app_dict],
    410412        }
    411413        context.update(extra_context or {})
  • new file django/contrib/auth/app.py

    diff --git a/django/contrib/auth/app.py b/django/contrib/auth/app.py
    new file mode 100644
    index 0000000..159b713
    - +  
     1from django import apps
     2from django.utils.translation import ugettext_lazy as _
     3
     4class AuthApp(apps.App):
     5
     6    class Meta:
     7        verbose_name = _('auth')
  • django/contrib/contenttypes/management.py

    diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py
    index 27d1275..a444714 100644
    a b  
     1from django.apps import cache, get_apps, get_models
    12from django.contrib.contenttypes.models import ContentType
    2 from django.db.models import get_apps, get_models, signals
     3from django.db.models import signals
    34from django.utils.encoding import smart_unicode
    45
    56def update_contenttypes(app, created_models, verbosity=2, **kwargs):
    def update_contenttypes(app, created_models, verbosity=2, **kwargs):  
    78    Creates content types for models in the given app, removing any model
    89    entries that no longer have a matching model class.
    910    """
     11    app_cls = cache.find_app_by_models_module(app)
    1012    ContentType.objects.clear_cache()
    11     content_types = list(ContentType.objects.filter(app_label=app.__name__.split('.')[-2]))
     13    content_types = list(ContentType.objects.filter(app_label=app_cls._meta.label))
    1214    app_models = get_models(app)
    1315    if not app_models:
    1416        return
  • django/contrib/staticfiles/finders.py

    diff --git a/django/contrib/staticfiles/finders.py b/django/contrib/staticfiles/finders.py
    index 45bf4a1..b23428b 100644
    a b  
    11import os
     2from django.apps import cache
    23from django.conf import settings
    34from django.core.exceptions import ImproperlyConfigured
    45from django.core.files.storage import default_storage, Storage, FileSystemStorage
    class AppDirectoriesFinder(BaseFinder):  
    113114    """
    114115    storage_class = AppStaticStorage
    115116
    116     def __init__(self, apps=None, *args, **kwargs):
     117    def __init__(self, *args, **kwargs):
    117118        # The list of apps that are handled
    118119        self.apps = []
    119120        # Mapping of app module paths to storage instances
    120121        self.storages = SortedDict()
    121         if apps is None:
    122             apps = settings.INSTALLED_APPS
    123         for app in apps:
     122        for app in cache.loaded_apps:
    124123            app_storage = self.storage_class(app)
    125124            if os.path.isdir(app_storage.location):
    126125                self.storages[app] = app_storage
  • django/contrib/staticfiles/storage.py

    diff --git a/django/contrib/staticfiles/storage.py b/django/contrib/staticfiles/storage.py
    index a804c56..ef04f20 100644
    a b class AppStaticStorage(FileSystemStorage):  
    194194        Returns a static file storage if available in the given app.
    195195        """
    196196        # app is the actual app module
    197         mod = import_module(app)
    198         mod_path = os.path.dirname(mod.__file__)
    199         location = os.path.join(mod_path, self.source_dir)
     197        location = os.path.join(app._meta.path, self.source_dir)
    200198        super(AppStaticStorage, self).__init__(location, *args, **kwargs)
    201199
    202200
  • django/core/management/__init__.py

    diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
    index 1345eaf..bf3790d 100644
    a b def get_commands():  
    9797
    9898        # Find the installed apps
    9999        try:
    100             from django.conf import settings
    101             apps = settings.INSTALLED_APPS
     100            from django.apps import cache
     101            apps = cache.loaded_apps
    102102        except (AttributeError, EnvironmentError, ImportError):
    103103            apps = []
    104104
    def get_commands():  
    111111            project_directory = None
    112112
    113113        # Find and load the management module for each installed app.
    114         for app_name in apps:
     114        for app in apps:
    115115            try:
    116                 path = find_management_module(app_name)
    117                 _commands.update(dict([(name, app_name)
     116                path = find_management_module(app._meta.name)
     117                _commands.update(dict([(name, app._meta.name)
    118118                                       for name in find_commands(path)]))
    119119            except ImportError:
    120120                pass # No management module - ignore this app
    class ManagementUtility(object):  
    316316                try:
    317317                    from django.conf import settings
    318318                    # Get the last part of the dotted path as the app name.
    319                     options += [(a.split('.')[-1], 0) for a in settings.INSTALLED_APPS]
     319                    options += [(a._meta.label, 0) for app in cache.loaded_apps]
    320320                except ImportError:
    321321                    # Fail silently if DJANGO_SETTINGS_MODULE isn't set. The
    322322                    # user will find out once they execute the command.
    def setup_environ(settings_mod, original_settings_path=None):  
    423423    project_module = import_module(project_name)
    424424    sys.path.pop()
    425425
     426    # Initialize the appcache and look for errors
     427    from django.apps import cache
     428    for (app_name, error) in cache.get_app_errors().items():
     429        sys.stderr.write("%s: %s" % (app_name, error))
     430        sys.exit(1)
     431
    426432    return project_directory
    427433
    428434def execute_from_command_line(argv=None):
  • django/core/management/commands/flush.py

    diff --git a/django/core/management/commands/flush.py b/django/core/management/commands/flush.py
    index bcadb96..dcb2a1a 100644
    a b  
    11from optparse import make_option
    22
     3from django.apps import cache
    34from django.conf import settings
    45from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
    56from django.core.management import call_command
    class Command(NoArgsCommand):  
    2930
    3031        # Import the 'management' module within each installed app, to register
    3132        # dispatcher events.
    32         for app_name in settings.INSTALLED_APPS:
     33        for app in cache.loaded_apps:
    3334            try:
    34                 import_module('.management', app_name)
     35                import_module('%s.management' % app._meta.name)
    3536            except ImportError:
    3637                pass
    3738
  • django/core/management/commands/syncdb.py

    diff --git a/django/core/management/commands/syncdb.py b/django/core/management/commands/syncdb.py
    index 4383c34..13b8224 100644
    a b  
    11from optparse import make_option
    22import sys
    33
     4from django.apps import cache
    45from django.conf import settings
    56from django.core.management.base import NoArgsCommand
    67from django.core.management.color import no_style
    class Command(NoArgsCommand):  
    1819            default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. '
    1920                'Defaults to the "default" database.'),
    2021    )
    21     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
     22    help = "Create the database tables for all installed apps whose tables haven't already been created."
    2223
    2324    def handle_noargs(self, **options):
    2425
    class Command(NoArgsCommand):  
    3435
    3536        # Import the 'management' module within each installed app, to register
    3637        # dispatcher events.
    37         for app_name in settings.INSTALLED_APPS:
     38        for app in cache.loaded_apps:
    3839            try:
    39                 import_module('.management', app_name)
     40                import_module('.management', app._meta.name)
    4041            except ImportError, exc:
    4142                # This is slightly hackish. We want to ignore ImportErrors
    4243                # if the "management" module itself is missing -- but we don't
    class Command(NoArgsCommand):  
    6364
    6465        # Build the manifest of apps and models that are to be synchronized
    6566        all_models = [
    66             (app.__name__.split('.')[-2],
    67                 [m for m in models.get_models(app, include_auto_created=True)
     67            (app._meta.label,
     68                [m for m in models.get_models(app._meta.models_module,
     69                                              include_auto_created=True)
    6870                if router.allow_syncdb(db, m)])
    69             for app in models.get_apps()
     71            for app in cache.loaded_apps
    7072        ]
    7173        def model_installed(model):
    7274            opts = model._meta
    class Command(NoArgsCommand):  
    101103                    cursor.execute(statement)
    102104                tables.append(connection.introspection.table_name_converter(model._meta.db_table))
    103105
    104 
    105106        transaction.commit_unless_managed(using=db)
    106107
    107108        # Send the post_syncdb signal, so individual apps can do whatever they need
  • django/core/management/sql.py

    diff --git a/django/core/management/sql.py b/django/core/management/sql.py
    index 298882f..1b170c2 100644
    a b  
    11import os
    22import re
    33
     4from django.apps import cache, get_models
    45from django.conf import settings
    56from django.core.management.base import CommandError
    67from django.db import models
    7 from django.db.models import get_models
    88
    99def sql_create(app, style, connection):
    1010    "Returns a list of the CREATE TABLE SQL statements for the given app."
    def custom_sql_for_model(model, style, connection):  
    182182def emit_post_sync_signal(created_models, verbosity, interactive, db):
    183183    # Emit the post_sync signal for every application.
    184184    for app in models.get_apps():
    185         app_name = app.__name__.split('.')[-2]
     185        app_cls = cache.find_app_by_models_module(app)
     186        app_name = app_cls._meta.label
    186187        if verbosity >= 2:
    187188            print "Running post-sync handlers for application", app_name
    188189        models.signals.post_syncdb.send(sender=app, app=app,
  • django/db/models/base.py

    diff --git a/django/db/models/base.py b/django/db/models/base.py
    index 71fd1f7..7891676 100644
    a b class ModelBase(type):  
    118118                else:
    119119                    base = parent
    120120            if base is None:
    121                     raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
     121                raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
    122122            if (new_class._meta.local_fields or
    123123                    new_class._meta.local_many_to_many):
    124124                raise FieldError("Proxy model '%s' contains model fields." % name)
  • django/db/models/loading.py

    diff --git a/django/db/models/loading.py b/django/db/models/loading.py
    index 03cdcc2..22c2c41 100644
    a b  
    1 "Utilities for loading models and the modules that contain them."
     1import warnings
    22
    3 from django.conf import settings
    4 from django.core.exceptions import ImproperlyConfigured
    5 from django.utils.datastructures import SortedDict
    6 from django.utils.importlib import import_module
    7 from django.utils.module_loading import module_has_submodule
     3from django.apps import (App, AppCache, cache,
     4    find_app, get_apps, get_app, get_app_errors, get_models, get_model,
     5    register_models, load_app, app_cache_ready)
    86
    9 import sys
    10 import os
    11 import threading
    12 
    13 __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
    14         'load_app', 'app_cache_ready')
    15 
    16 class AppCache(object):
    17     """
    18     A cache that stores installed applications and their models. Used to
    19     provide reverse-relations and for app introspection (e.g. admin).
    20     """
    21     # Use the Borg pattern to share state between all instances. Details at
    22     # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531.
    23     __shared_state = dict(
    24         # Keys of app_store are the model modules for each application.
    25         app_store = SortedDict(),
    26 
    27         # Mapping of installed app_labels to model modules for that app.
    28         app_labels = {},
    29 
    30         # Mapping of app_labels to a dictionary of model names to model code.
    31         # May contain apps that are not installed.
    32         app_models = SortedDict(),
    33 
    34         # Mapping of app_labels to errors raised when trying to import the app.
    35         app_errors = {},
    36 
    37         # -- Everything below here is only used when populating the cache --
    38         loaded = False,
    39         handled = {},
    40         postponed = [],
    41         nesting_level = 0,
    42         write_lock = threading.RLock(),
    43         _get_models_cache = {},
    44     )
    45 
    46     def __init__(self):
    47         self.__dict__ = self.__shared_state
    48 
    49     def _populate(self):
    50         """
    51         Fill in all the cache information. This method is threadsafe, in the
    52         sense that every caller will see the same state upon return, and if the
    53         cache is already initialised, it does no work.
    54         """
    55         if self.loaded:
    56             return
    57         self.write_lock.acquire()
    58         try:
    59             if self.loaded:
    60                 return
    61             for app_name in settings.INSTALLED_APPS:
    62                 if app_name in self.handled:
    63                     continue
    64                 self.load_app(app_name, True)
    65             if not self.nesting_level:
    66                 for app_name in self.postponed:
    67                     self.load_app(app_name)
    68                 self.loaded = True
    69         finally:
    70             self.write_lock.release()
    71 
    72     def _label_for(self, app_mod):
    73         """
    74         Return app_label for given models module.
    75 
    76         """
    77         return app_mod.__name__.split('.')[-2]
    78 
    79     def load_app(self, app_name, can_postpone=False):
    80         """
    81         Loads the app with the provided fully qualified name, and returns the
    82         model module.
    83         """
    84         self.handled[app_name] = None
    85         self.nesting_level += 1
    86         app_module = import_module(app_name)
    87         try:
    88             models = import_module('.models', app_name)
    89         except ImportError:
    90             self.nesting_level -= 1
    91             # If the app doesn't have a models module, we can just ignore the
    92             # ImportError and return no models for it.
    93             if not module_has_submodule(app_module, 'models'):
    94                 return None
    95             # But if the app does have a models module, we need to figure out
    96             # whether to suppress or propagate the error. If can_postpone is
    97             # True then it may be that the package is still being imported by
    98             # Python and the models module isn't available yet. So we add the
    99             # app to the postponed list and we'll try it again after all the
    100             # recursion has finished (in populate). If can_postpone is False
    101             # then it's time to raise the ImportError.
    102             else:
    103                 if can_postpone:
    104                     self.postponed.append(app_name)
    105                     return None
    106                 else:
    107                     raise
    108 
    109         self.nesting_level -= 1
    110         if models not in self.app_store:
    111             self.app_store[models] = len(self.app_store)
    112             self.app_labels[self._label_for(models)] = models
    113         return models
    114 
    115     def app_cache_ready(self):
    116         """
    117         Returns true if the model cache is fully populated.
    118 
    119         Useful for code that wants to cache the results of get_models() for
    120         themselves once it is safe to do so.
    121         """
    122         return self.loaded
    123 
    124     def get_apps(self):
    125         "Returns a list of all installed modules that contain models."
    126         self._populate()
    127 
    128         # Ensure the returned list is always in the same order (with new apps
    129         # added at the end). This avoids unstable ordering on the admin app
    130         # list page, for example.
    131         apps = [(v, k) for k, v in self.app_store.items()]
    132         apps.sort()
    133         return [elt[1] for elt in apps]
    134 
    135     def get_app(self, app_label, emptyOK=False):
    136         """
    137         Returns the module containing the models for the given app_label. If
    138         the app has no models in it and 'emptyOK' is True, returns None.
    139         """
    140         self._populate()
    141         self.write_lock.acquire()
    142         try:
    143             for app_name in settings.INSTALLED_APPS:
    144                 if app_label == app_name.split('.')[-1]:
    145                     mod = self.load_app(app_name, False)
    146                     if mod is None:
    147                         if emptyOK:
    148                             return None
    149                     else:
    150                         return mod
    151             raise ImproperlyConfigured("App with label %s could not be found" % app_label)
    152         finally:
    153             self.write_lock.release()
    154 
    155     def get_app_errors(self):
    156         "Returns the map of known problems with the INSTALLED_APPS."
    157         self._populate()
    158         return self.app_errors
    159 
    160     def get_models(self, app_mod=None,
    161                    include_auto_created=False, include_deferred=False,
    162                    only_installed=True):
    163         """
    164         Given a module containing models, returns a list of the models.
    165         Otherwise returns a list of all installed models.
    166 
    167         By default, auto-created models (i.e., m2m models without an
    168         explicit intermediate table) are not included. However, if you
    169         specify include_auto_created=True, they will be.
    170 
    171         By default, models created to satisfy deferred attribute
    172         queries are *not* included in the list of models. However, if
    173         you specify include_deferred, they will be.
    174         """
    175         cache_key = (app_mod, include_auto_created, include_deferred, only_installed)
    176         try:
    177             return self._get_models_cache[cache_key]
    178         except KeyError:
    179             pass
    180         self._populate()
    181         if app_mod:
    182             if app_mod in self.app_store:
    183                 app_list = [self.app_models.get(self._label_for(app_mod),
    184                                                 SortedDict())]
    185             else:
    186                 app_list = []
    187         else:
    188             if only_installed:
    189                 app_list = [self.app_models.get(app_label, SortedDict())
    190                             for app_label in self.app_labels.iterkeys()]
    191             else:
    192                 app_list = self.app_models.itervalues()
    193         model_list = []
    194         for app in app_list:
    195             model_list.extend(
    196                 model for model in app.values()
    197                 if ((not model._deferred or include_deferred) and
    198                     (not model._meta.auto_created or include_auto_created))
    199             )
    200         self._get_models_cache[cache_key] = model_list
    201         return model_list
    202 
    203     def get_model(self, app_label, model_name,
    204                   seed_cache=True, only_installed=True):
    205         """
    206         Returns the model matching the given app_label and case-insensitive
    207         model_name.
    208 
    209         Returns None if no model is found.
    210         """
    211         if seed_cache:
    212             self._populate()
    213         if only_installed and app_label not in self.app_labels:
    214             return None
    215         return self.app_models.get(app_label, SortedDict()).get(model_name.lower())
    216 
    217     def register_models(self, app_label, *models):
    218         """
    219         Register a set of models as belonging to an app.
    220         """
    221         for model in models:
    222             # Store as 'name: model' pair in a dictionary
    223             # in the app_models dictionary
    224             model_name = model._meta.object_name.lower()
    225             model_dict = self.app_models.setdefault(app_label, SortedDict())
    226             if model_name in model_dict:
    227                 # The same model may be imported via different paths (e.g.
    228                 # appname.models and project.appname.models). We use the source
    229                 # filename as a means to detect identity.
    230                 fname1 = os.path.abspath(sys.modules[model.__module__].__file__)
    231                 fname2 = os.path.abspath(sys.modules[model_dict[model_name].__module__].__file__)
    232                 # Since the filename extension could be .py the first time and
    233                 # .pyc or .pyo the second time, ignore the extension when
    234                 # comparing.
    235                 if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]:
    236                     continue
    237             model_dict[model_name] = model
    238         self._get_models_cache.clear()
    239 
    240 cache = AppCache()
    241 
    242 # These methods were always module level, so are kept that way for backwards
    243 # compatibility.
    244 get_apps = cache.get_apps
    245 get_app = cache.get_app
    246 get_app_errors = cache.get_app_errors
    247 get_models = cache.get_models
    248 get_model = cache.get_model
    249 register_models = cache.register_models
    250 load_app = cache.load_app
    251 app_cache_ready = cache.app_cache_ready
     7warnings.warn(
     8    'The utilities in django.db.models.loading have been moved to '
     9    'django.apps. Please update your code accordingly.',
     10    PendingDeprecationWarning)
  • django/db/models/options.py

    diff --git a/django/db/models/options.py b/django/db/models/options.py
    index 6f0f406..5d19fe9 100644
    a b  
    11import re
    22from bisect import bisect
    33
     4from django.apps import cache
    45from django.conf import settings
    56from django.db.models.related import RelatedObject
    67from django.db.models.fields.related import ManyToManyRel
    from django.db.models.loading import get_models, app_cache_ready  
    1011from django.utils.translation import activate, deactivate_all, get_language, string_concat
    1112from django.utils.encoding import force_unicode, smart_str
    1213from django.utils.datastructures import SortedDict
     14from django.utils.text import get_verbose_name
    1315
    14 # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
    15 get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
    1616
    1717DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
    1818                 'unique_together', 'permissions', 'get_latest_by',
    class Options(object):  
    5959        from django.db.backends.util import truncate_name
    6060
    6161        cls._meta = self
    62         self.installed = re.sub('\.models$', '', cls.__module__) in settings.INSTALLED_APPS
     62        # The AppCache sets this attribute to True for apps that are installed
     63        self.installed = False
    6364        # First, construct the default values for these options.
    6465        self.object_name = cls.__name__
    6566        self.module_name = self.object_name.lower()
    class Options(object):  
    100101            self.verbose_name_plural = string_concat(self.verbose_name, 's')
    101102        del self.meta
    102103
    103         # If the db_table wasn't provided, use the app_label + module_name.
     104        # If the db_table wasn't provided, use the db_prefix + module_name.
     105        # Or use the app label when no app instance was found, which happens
     106        # when the app cache is not initialized but the model is imported
    104107        if not self.db_table:
    105             self.db_table = "%s_%s" % (self.app_label, self.module_name)
    106             self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
     108            app = cache.find_app(self.app_label)
     109            prefix = app and app._meta.db_prefix or self.app_label
     110            self.db_table = truncate_name("%s_%s" % (prefix, self.module_name),
     111                                          connection.ops.max_name_length())
    107112
    108113    def _prepare(self, model):
    109114        if self.order_with_respect_to:
  • django/template/base.py

    diff --git a/django/template/base.py b/django/template/base.py
    index 9a7f55f..0acda61 100644
    a b import re  
    22from functools import partial
    33from inspect import getargspec
    44
     5from django.apps import cache
    56from django.conf import settings
    67from django.template.context import Context, RequestContext, ContextPopException
    78from django.utils.importlib import import_module
    def get_templatetags_modules():  
    10461047    if not templatetags_modules:
    10471048        _templatetags_modules = []
    10481049        # Populate list once per thread.
    1049         for app_module in ['django'] + list(settings.INSTALLED_APPS):
     1050        for app_module in ['django'] + [app._meta.name for app in cache.loaded_apps]:
    10501051            try:
    10511052                templatetag_module = '%s.templatetags' % app_module
    10521053                import_module(templatetag_module)
  • django/template/loaders/app_directories.py

    diff --git a/django/template/loaders/app_directories.py b/django/template/loaders/app_directories.py
    index b0560b4..b401e6c 100644
    a b packages.  
    66import os
    77import sys
    88
     9from django.apps import cache
    910from django.conf import settings
    1011from django.core.exceptions import ImproperlyConfigured
    1112from django.template.base import TemplateDoesNotExist
    from django.utils.importlib import import_module  
    1617# At compile time, cache the directories to search.
    1718fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
    1819app_template_dirs = []
    19 for app in settings.INSTALLED_APPS:
    20     try:
    21         mod = import_module(app)
    22     except ImportError, e:
    23         raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
    24     template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
     20for app in cache.loaded_apps:
     21    template_dir = os.path.join(app._meta.path, 'templates')
    2522    if os.path.isdir(template_dir):
    2623        app_template_dirs.append(template_dir.decode(fs_encoding))
    2724
  • django/template/loaders/eggs.py

    diff --git a/django/template/loaders/eggs.py b/django/template/loaders/eggs.py
    index 42f87a4..a5ef838 100644
    a b  
    11# Wrapper for loading templates from eggs via pkg_resources.resource_string.
     2from django.apps import cache
    23
    34try:
    45    from pkg_resources import resource_string
    class Loader(BaseLoader):  
    2021        """
    2122        if resource_string is not None:
    2223            pkg_name = 'templates/' + template_name
    23             for app in settings.INSTALLED_APPS:
     24            for app in cache.loaded_apps:
    2425                try:
    25                     return (resource_string(app, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app, pkg_name))
    26                 except:
     26                    return (resource_string(app._meta.name, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app._meta.name, pkg_name))
     27                except Exception, e:
    2728                    pass
    2829        raise TemplateDoesNotExist(template_name)
    2930
  • django/utils/module_loading.py

    diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py
    index 26a7e51..54c04e9 100644
    a b def module_has_submodule(package, module_name):  
    1414    for finder in sys.meta_path:
    1515        if finder.find_module(name, package.__path__):
    1616            return True
     17    # If this isn't really a package return False right away
     18    if not hasattr(package, '__path__'):
     19        return False
    1720    for entry in package.__path__:  # No __path__, then not a package.
    1821        try:
    1922            # Try the cached finder.
  • django/utils/text.py

    diff --git a/django/utils/text.py b/django/utils/text.py
    index 14555dd..2afb2b0 100644
    a b def unescape_entities(text):  
    362362unescape_entities = allow_lazy(unescape_entities, unicode)
    363363
    364364def unescape_string_literal(s):
    365     r"""
    366     Convert quoted string literals to unquoted strings with escaped quotes and
    367     backslashes unquoted::
     365    """
     366    Converts quoted string literals to unquoted strings with escaped quotes
     367    and backslashes unquoted::
    368368
    369369        >>> unescape_string_literal('"abc"')
    370370        'abc'
    def unescape_string_literal(s):  
    380380    quote = s[0]
    381381    return s[1:-1].replace(r'\%s' % quote, quote).replace(r'\\', '\\')
    382382unescape_string_literal = allow_lazy(unescape_string_literal)
     383
     384def get_verbose_name(class_name):
     385    """
     386    Calculates the verbose_name by converting from
     387    InitialCaps to "lowercase with spaces".
     388    """
     389    new = re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name)
     390    return new.lower().strip()
  • django/utils/translation/trans_real.py

    diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
    index 71765e7..5eefd70 100644
    a b try:  
    1212except ImportError:
    1313    from StringIO import StringIO
    1414
     15from django.apps import cache
    1516from django.utils.importlib import import_module
    1617from django.utils.safestring import mark_safe, SafeData
    1718
    def translation(language):  
    156157                    res.merge(t)
    157158            return res
    158159
    159         for appname in reversed(settings.INSTALLED_APPS):
    160             app = import_module(appname)
    161             apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
     160        for app in reversed(cache.loaded_apps):
     161            apppath = os.path.join(app._meta.path, 'locale')
    162162
    163163            if os.path.isdir(apppath):
    164164                res = _merge(apppath)
  • django/views/i18n.py

    diff --git a/django/views/i18n.py b/django/views/i18n.py
    index 140dc54..055323e 100644
    a b import os  
    22import gettext as gettext_module
    33
    44from django import http
     5from django.apps import cache
    56from django.conf import settings
    67from django.utils import importlib
    78from django.utils.translation import check_for_language, activate, to_locale, get_language
    def javascript_catalog(request, domain='djangojs', packages=None):  
    186187        packages = ['django.conf']
    187188    if isinstance(packages, basestring):
    188189        packages = packages.split('+')
    189     packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS]
     190    apps = [app._meta.name for app in cache.loaded_apps]
     191    packages = [p for p in packages if p == 'django.conf' or p in apps]
    190192    default_locale = to_locale(settings.LANGUAGE_CODE)
    191193    locale = to_locale(get_language())
    192194    t = {}
  • new file tests/appcachetests/anothermodel_app/app.py

    diff --git a/tests/appcachetests/anothermodel_app/__init__.py b/tests/appcachetests/anothermodel_app/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/appcachetests/anothermodel_app/app.py b/tests/appcachetests/anothermodel_app/app.py
    new file mode 100644
    index 0000000..7433592
    - +  
     1from django import apps
     2
     3class MyApp(apps.App):
     4
     5    class Meta:
     6        models_path = 'model_app.othermodels'
     7
     8class MyOtherApp(MyApp):
     9
     10    class Meta:
     11        db_prefix = 'nomodel_app'
  • new file tests/appcachetests/anothermodel_app/models.py

    diff --git a/tests/appcachetests/anothermodel_app/models.py b/tests/appcachetests/anothermodel_app/models.py
    new file mode 100644
    index 0000000..cd849d1
    - +  
     1from django.db import models
     2
     3class Job(models.Model):
     4    name = models.CharField(max_length=30)
     5
     6class Person(models.Model):
     7    first_name = models.CharField(max_length=30)
     8    last_name = models.CharField(max_length=30)
     9    jobs = models.ManyToManyField(Job)
     10
     11class Contact(models.Model):
     12    person = models.ForeignKey(Person)
  • new file tests/appcachetests/anothermodel_app/othermodels.py

    diff --git a/tests/appcachetests/anothermodel_app/othermodels.py b/tests/appcachetests/anothermodel_app/othermodels.py
    new file mode 100644
    index 0000000..ffb04e8
    - +  
     1from django.db import models
     2
     3class Person(models.Model):
     4    first_name = models.CharField(max_length=30)
     5    last_name = models.CharField(max_length=30)
  • new file tests/appcachetests/model_app/app.py

    diff --git a/tests/appcachetests/eggs/brokenapp.egg b/tests/appcachetests/eggs/brokenapp.egg
    new file mode 100755
    index 0000000..8aca671
    Binary files /dev/null and b/tests/appcachetests/eggs/brokenapp.egg differ
    diff --git a/tests/appcachetests/eggs/modelapp.egg b/tests/appcachetests/eggs/modelapp.egg
    new file mode 100755
    index 0000000..c2370b5
    Binary files /dev/null and b/tests/appcachetests/eggs/modelapp.egg differ
    diff --git a/tests/appcachetests/eggs/nomodelapp.egg b/tests/appcachetests/eggs/nomodelapp.egg
    new file mode 100755
    index 0000000..5b8d217
    Binary files /dev/null and b/tests/appcachetests/eggs/nomodelapp.egg differ
    diff --git a/tests/appcachetests/eggs/omelet.egg b/tests/appcachetests/eggs/omelet.egg
    new file mode 100755
    index 0000000..bd1c687
    Binary files /dev/null and b/tests/appcachetests/eggs/omelet.egg differ
    diff --git a/tests/appcachetests/model_app/__init__.py b/tests/appcachetests/model_app/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/appcachetests/model_app/app.py b/tests/appcachetests/model_app/app.py
    new file mode 100644
    index 0000000..3a3e307
    - +  
     1from django import apps
     2
     3class MyApp(apps.App):
     4
     5    class Meta:
     6        models_path = 'model_app.othermodels'
     7
     8class MyOtherApp(MyApp):
     9
     10    class Meta(MyApp.Meta):
     11        db_prefix = 'nomodel_app'
     12
     13
     14class MySecondApp(MyOtherApp):
     15
     16    class Meta(MyOtherApp.Meta):
     17        models_path = 'model_app.models'
     18
     19
     20class YetAnotherApp(apps.App):
     21
     22    class Meta:
     23        models_path = 'model_app.yetanother'
     24
     25
     26class MyThirdApp(YetAnotherApp, MySecondApp):
     27
     28    class Meta(YetAnotherApp.Meta, MySecondApp.Meta):
     29        pass
     30
     31
     32class MyOverrideApp(MyOtherApp):
     33
     34    pass
  • new file tests/appcachetests/model_app/models.py

    diff --git a/tests/appcachetests/model_app/models.py b/tests/appcachetests/model_app/models.py
    new file mode 100644
    index 0000000..ffb04e8
    - +  
     1from django.db import models
     2
     3class Person(models.Model):
     4    first_name = models.CharField(max_length=30)
     5    last_name = models.CharField(max_length=30)
  • new file tests/appcachetests/model_app/othermodels.py

    diff --git a/tests/appcachetests/model_app/othermodels.py b/tests/appcachetests/model_app/othermodels.py
    new file mode 100644
    index 0000000..ffb04e8
    - +  
     1from django.db import models
     2
     3class Person(models.Model):
     4    first_name = models.CharField(max_length=30)
     5    last_name = models.CharField(max_length=30)
  • new file tests/appcachetests/nomodel_app/app.py

    diff --git a/tests/appcachetests/model_app/yetanother.py b/tests/appcachetests/model_app/yetanother.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/appcachetests/nomodel_app/__init__.py b/tests/appcachetests/nomodel_app/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/appcachetests/nomodel_app/app.py b/tests/appcachetests/nomodel_app/app.py
    new file mode 100644
    index 0000000..194278e
    - +  
     1from django import apps
     2
     3class MyApp(apps.App):
     4    pass
     5
     6class ObjectApp(object):
     7    pass
     8 No newline at end of file
  • new file tests/appcachetests/same_label/model_app/models.py

    diff --git a/tests/appcachetests/same_label/__init__.py b/tests/appcachetests/same_label/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/appcachetests/same_label/model_app/__init__.py b/tests/appcachetests/same_label/model_app/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/appcachetests/same_label/model_app/models.py b/tests/appcachetests/same_label/model_app/models.py
    new file mode 100644
    index 0000000..ffb04e8
    - +  
     1from django.db import models
     2
     3class Person(models.Model):
     4    first_name = models.CharField(max_length=30)
     5    last_name = models.CharField(max_length=30)
  • new file tests/appcachetests/same_label/nomodel_app/app.py

    diff --git a/tests/appcachetests/same_label/nomodel_app/__init__.py b/tests/appcachetests/same_label/nomodel_app/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/appcachetests/same_label/nomodel_app/app.py b/tests/appcachetests/same_label/nomodel_app/app.py
    new file mode 100644
    index 0000000..86993e0
    - +  
     1from django import apps
     2
     3class MyApp(apps.App):
     4    pass
  • new file tests/appcachetests/tests.py

    diff --git a/tests/appcachetests/tests.py b/tests/appcachetests/tests.py
    new file mode 100755
    index 0000000..113efe0
    - +  
     1#!/usr/bin/env python
     2import os
     3import sys
     4import unittest
     5import threading
     6
     7from django.apps import cache
     8from django.apps.cache import _initialize
     9from django.apps.signals import app_loaded, post_apps_loaded
     10from django.conf import settings
     11from django.core.exceptions import ImproperlyConfigured
     12from django.utils.datastructures import SortedDict
     13
     14# remove when tests are integrated into the django testsuite
     15settings.configure()
     16
     17
     18class AppCacheTestCase(unittest.TestCase):
     19    """
     20    TestCase that resets the AppCache after each test.
     21    """
     22    def setUp(self):
     23        self.old_installed_apps = settings.INSTALLED_APPS
     24        settings.INSTALLED_APPS = ()
     25        settings.DATABASES = {
     26            'default': {
     27                'ENGINE': 'django.db.backends.sqlite3',
     28                'NAME': ':memory:'
     29            }
     30        }
     31
     32    def tearDown(self):
     33        settings.INSTALLED_APPS = self.old_installed_apps
     34        cache._reset()
     35
     36class ReloadTests(AppCacheTestCase):
     37    """
     38    Tests for the _reload function
     39    """
     40
     41    def test_reload(self):
     42        """
     43        Test reloading the cache
     44        """
     45        settings.INSTALLED_APPS = ('model_app',)
     46        cache._populate()
     47        self.assertEquals(len(cache.loaded_apps), 1)
     48        self.assertEquals(cache.loaded_apps[0]._meta.name, 'model_app')
     49        settings.INSTALLED_APPS = ('anothermodel_app', 'model_app')
     50        cache._reload()
     51        self.assertEquals(len(cache.loaded_apps), 2)
     52        self.assertEquals(cache.loaded_apps[0]._meta.name, 'anothermodel_app')
     53
     54    def test_reload_register_models(self):
     55        """
     56        Test that models are registered with the cache again after it
     57        was reloaded
     58        """
     59        settings.INSTALLED_APPS = ('model_app',)
     60        cache._populate()
     61        self.assertTrue('model_app' in cache.app_models)
     62        cache._reload()
     63        self.assertTrue('model_app' in cache.app_models)
     64
     65
     66class AppCacheReadyTests(AppCacheTestCase):
     67    """
     68    Tests for the app_cache_ready function that indicates if the cache
     69    is fully populated.
     70    """
     71
     72    def test_not_initialized(self):
     73        """
     74        Should return False if the AppCache hasn't been initialized
     75        """
     76        self.assertFalse(cache.app_cache_ready())
     77
     78    def test_load_app(self):
     79        """
     80        Should return False after executing the load_app function
     81        """
     82        cache.load_app('nomodel_app')
     83        self.assertFalse(cache.app_cache_ready())
     84        cache.load_app('nomodel_app', can_postpone=True)
     85        self.assertFalse(cache.app_cache_ready())
     86
     87
     88class GetAppClassTests(AppCacheTestCase):
     89    """Tests for the get_app_class function"""
     90
     91    def test_app_class(self):
     92        """
     93        Tests that the full path app class is returned
     94        """
     95        settings.INSTALLED_APPS = ('model_app.app.MyApp',)
     96        from model_app.app import MyApp
     97        app_class = cache.get_app_class(settings.INSTALLED_APPS[0])
     98        self.assertEquals(app_class, MyApp)
     99
     100    def test_one_level_module(self):
     101        """
     102        Tests that a new app class is generated for an one level app module
     103        """
     104        settings.INSTALLED_APPS = ('model_app',)
     105        app_class = cache.get_app_class(settings.INSTALLED_APPS[0])
     106        self.assertEquals(app_class.__name__, 'ModelApp')
     107
     108    def test_multi_level_module(self):
     109        """
     110        Tests that a new app class is generated for a multiple level app module
     111        """
     112        settings.INSTALLED_APPS = ('django.contrib.admin',)
     113        app_class = cache.get_app_class(settings.INSTALLED_APPS[0])
     114        self.assertEquals(app_class.__name__, 'Admin')
     115
     116    def test_defunct_module(self):
     117        """
     118        Tests that a wrong module raises an ImproperlyConfigured exception
     119        """
     120        settings.INSTALLED_APPS = ('lalalala.admin',)
     121        self.assertRaises(ImproperlyConfigured, cache.get_app_class,
     122                          settings.INSTALLED_APPS[0])
     123
     124    def test_missing_attribute(self):
     125        """
     126        Tests that a missing attribute raises an ImproperlyConfigured exception
     127        """
     128        settings.INSTALLED_APPS = ('nomodel_app.app.NotThereApp',)
     129        self.assertRaises(ImproperlyConfigured, cache.get_app_class,
     130                          settings.INSTALLED_APPS[0])
     131
     132    def test_incorrect_subclass(self):
     133        """
     134        Tests that a class not subclassing django.apps.App raises an
     135        ImproperlyConfigured exception
     136        """
     137        settings.INSTALLED_APPS = ('nomodel_app.app.ObjectApp',)
     138        self.assertRaises(ImproperlyConfigured, cache.get_app_class,
     139                          settings.INSTALLED_APPS[0])
     140
     141
     142class GetAppsTests(AppCacheTestCase):
     143    """Tests for the get_apps function"""
     144
     145    def test_app_classes(self):
     146        """
     147        Test that the correct models modules are returned for app classes
     148        installed via the INSTALLED_APPS setting
     149        """
     150        settings.INSTALLED_APPS = ('model_app.app.MyApp',)
     151        apps = cache.get_apps()
     152        self.assertTrue(cache.app_cache_ready())
     153        self.assertEquals(apps[0].__name__, 'model_app.othermodels')
     154
     155    def test_installed_apps(self):
     156        """
     157        Test that the correct models modules are returned for apps installed
     158        via the INSTALLED_APPS setting
     159        """
     160        settings.INSTALLED_APPS = ('model_app',)
     161        apps = cache.get_apps()
     162        self.assertTrue(cache.app_cache_ready())
     163        self.assertEquals(apps[0].__name__, 'model_app.models')
     164
     165    def test_same_app_in_both_settings(self):
     166        """
     167        Test that if an App is listed multiple times in INSTALLED_APPS
     168        only one of them is loaded
     169        """
     170        settings.INSTALLED_APPS = ('model_app.app.MyApp', 'model_app')
     171        apps = cache.get_apps()
     172        self.assertEquals(len(apps), 1)
     173        self.assertEquals(apps[0].__name__, 'model_app.othermodels')
     174
     175    def test_empty_models(self):
     176        """
     177        Test that modules that don't contain models are not returned
     178        """
     179        settings.INSTALLED_APPS = ('nomodel_app',)
     180        self.assertEqual(cache.get_apps(), [])
     181        self.assertTrue(cache.app_cache_ready())
     182
     183    def test_db_prefix_exception(self):
     184        """
     185        Test that an exception is raised if two app instances
     186        have the same db_prefix attribute
     187        """
     188        settings.INSTALLED_APPS = ('nomodel_app.app.MyApp',
     189                                   'model_app.app.MyOtherApp')
     190        self.assertRaises(ImproperlyConfigured, cache.get_apps)
     191
     192
     193class GetAppTests(AppCacheTestCase):
     194    """Tests for the get_app function"""
     195
     196    def test_installed_apps(self):
     197        """
     198        Test that the correct module is returned when the app was installed
     199        via the INSTALLED_APPS setting
     200        """
     201        settings.INSTALLED_APPS = ('model_app',)
     202        mod = cache.get_app('model_app')
     203        self.assertTrue(cache.app_cache_ready())
     204        self.assertEquals(mod.__name__, 'model_app.models')
     205
     206    def test_not_found_exception(self):
     207        """
     208        Test that an ImproperlyConfigured exception is raised if an app
     209        could not be found
     210        """
     211        self.assertRaises(ImproperlyConfigured, cache.get_app,
     212                          'notarealapp')
     213        self.assertTrue(cache.app_cache_ready())
     214
     215    def test_emptyOK(self):
     216        """
     217        Test that None is returned if emptyOK is True and the module
     218        has no models
     219        """
     220        settings.INSTALLED_APPS = ('nomodel_app',)
     221        module = cache.get_app('nomodel_app', emptyOK=True)
     222        self.assertTrue(cache.app_cache_ready())
     223        self.failUnless(module is None)
     224
     225    def test_exception_if_no_models(self):
     226        """
     227        Test that an ImproperlyConfigured exception is raised if the app
     228        has no modules and the emptyOK arg is False
     229        """
     230        settings.INSTALLED_APPS = ('nomodel_app',)
     231        self.assertRaises(ImproperlyConfigured, cache.get_app,
     232                          'nomodel_app')
     233        self.assertTrue(cache.app_cache_ready())
     234
     235
     236class GetAppErrorsTests(AppCacheTestCase):
     237    """Tests for the get_app_errors function"""
     238
     239    def test_get_app_errors(self):
     240        """Test that the function returns an empty dict"""
     241        self.assertEqual(cache.get_app_errors(), {})
     242        self.assertTrue(cache.app_cache_ready())
     243
     244
     245class GetModelsTests(AppCacheTestCase):
     246    """Tests for the get_models function"""
     247
     248    def test_installed(self):
     249        """
     250        Test that only models from apps are returned that are listed in
     251        the INSTALLED_APPS setting
     252        """
     253        from anothermodel_app.models import Person
     254        from model_app.models import Person
     255        settings.INSTALLED_APPS = ('model_app',)
     256        models = cache.get_models()
     257        self.assertTrue(cache.app_cache_ready())
     258        self.assertEqual(models, [Person])
     259
     260    def test_not_only_installed(self):
     261        """
     262        Test that not only installed models are returned
     263        """
     264        from anothermodel_app.models import Job, Person, Contact
     265        from model_app.models import Person as p2
     266        settings.INSTALLED_APPS = ('model_app',)
     267        models = cache.get_models(only_installed=False)
     268        self.assertTrue(cache.app_cache_ready())
     269        self.assertEqual(models, [Job, Person, Contact, p2])
     270
     271    def test_app_mod(self):
     272        """
     273        Test that the correct models are returned if an models module is
     274        passed and the app is listed in INSTALLED_APPS
     275        """
     276        from model_app import models
     277        from model_app.models import Person
     278        settings.INSTALLED_APPS = ('model_app', 'anothermodel_app')
     279        models = cache.get_models(app_mod=models)
     280        self.assertTrue(cache.app_cache_ready())
     281        self.assertEqual(models, [Person])
     282
     283    def test_app_mod_not_installed(self):
     284        """
     285        Test that no models are returned when a models module is
     286        passed and the app is _not_ listed in INSTALLED_APPS
     287        """
     288        from model_app import models
     289        from model_app.models import Person
     290        models = cache.get_models(app_mod=models)
     291        self.assertEqual(models, [])
     292
     293    def test_include_auto_created(self):
     294        """
     295        Test that auto created models are included
     296        """
     297        settings.INSTALLED_APPS = ('anothermodel_app',)
     298        models = cache.get_models(include_auto_created=True)
     299        self.assertTrue(cache.app_cache_ready())
     300        from anothermodel_app.models import Job, Person
     301        self.assertEqual(models[0], Job)
     302        self.assertEqual(models[1].__name__, 'Person_jobs')
     303        self.assertEqual(models[2], Person)
     304
     305    def test_related_objects_cache(self):
     306        """
     307        Test that the related objects cache is filled correctly
     308        """
     309        from anothermodel_app.models import Contact
     310        self.assertEqual(Contact._meta.get_all_field_names(),
     311                         ['id', 'person'])
     312
     313    def test_related_many_to_many_cache(self):
     314        """
     315        Test that the related m2m cache is filled correctly
     316        """
     317        from anothermodel_app.models import Job
     318        self.assertEqual(Job._meta.get_all_field_names(),
     319                         ['id', 'name', 'person'])
     320
     321
     322class GetModelTests(AppCacheTestCase):
     323    """Tests for the get_model function"""
     324
     325    def test_seeded_only_installed_valid(self):
     326        """
     327        Test that the correct model is returned if the cache is seeded
     328        and only models from apps listed in INSTALLED_APPS should be returned
     329        """
     330        settings.INSTALLED_APPS = ('model_app',)
     331        model = cache.get_model('model_app', 'Person')
     332        self.assertEqual(model.__name__, 'Person')
     333        self.assertTrue(cache.app_cache_ready())
     334
     335    def test_seeded_only_installed_invalid(self):
     336        """
     337        Test that None is returned if the cache is seeded but the model
     338        was not registered with the cache
     339        """
     340        model = cache.get_model('model_app', 'Person')
     341        self.assertEqual(model, None)
     342        self.assertTrue(cache.app_cache_ready())
     343
     344    def test_unseeded_only_installed_invalid(self):
     345        """
     346        Test that None is returned if the cache is unseeded and the model
     347        was not registered with the cache
     348        """
     349        model = cache.get_model('model_app', 'Person', seed_cache=False)
     350        self.assertEqual(model, None)
     351        self.assertFalse(cache.app_cache_ready())
     352
     353    def test_seeded_all_models_valid(self):
     354        """
     355        Test that the correct model is returned if the cache is seeded and
     356        all models (including unbound) should be returned
     357        """
     358        cache._populate()
     359        from model_app.models import Person
     360        model = cache.get_model('model_app', 'Person', only_installed=False)
     361        self.assertEquals(model, Person)
     362
     363    def test_seeded_all_models_invalid(self):
     364        """
     365        Test that None is returned if the cache is seeded and all models
     366        should be returned, but the model wasnt registered with the cache
     367        """
     368        cache._populate()
     369        model = cache.get_model('model_app', 'Person', only_installed=False)
     370        self.assertEquals(model, None)
     371
     372    def test_unseeded_all_models_valid(self):
     373        """
     374        Test that the correct model is returned if the cache is unseeded and
     375        all models should be returned
     376        """
     377        from model_app.models import Person
     378        model = cache.get_model('model_app', 'Person', seed_cache=False, only_installed=False)
     379        self.assertEquals(model, Person)
     380
     381    def test_unseeded_all_models_invalid(self):
     382        """
     383        Test that None is returned if the cache is unseeded, all models should
     384        be returned but the model wasn't registered with the cache
     385        """
     386        model = cache.get_model('model_app', 'Person', seed_cache=False, only_installed=False)
     387        self.assertEquals(model, None)
     388
     389class LoadAppTests(AppCacheTestCase):
     390    """Tests for the load_app function"""
     391
     392    def test_with_models(self):
     393        """
     394        Test that an app instance is created and the models
     395        module is returned
     396        """
     397        mod = cache.load_app('model_app')
     398        app = cache.loaded_apps[0]
     399        self.assertEqual(len(cache.loaded_apps), 1)
     400        self.assertEqual(app._meta.name, 'model_app')
     401        self.assertEqual(app._meta.models_module.__name__, 'model_app.models')
     402        self.assertEqual(mod.__name__, 'model_app.models')
     403
     404    def test_with_inheritance(self):
     405        from model_app.app import MyApp
     406        mod = cache.load_app('model_app.app.MyOtherApp')
     407        app = cache.loaded_apps[0]
     408        self.assertEqual(app._meta.name, 'model_app')
     409        self.assertEqual(app._meta.models_module.__name__, 'model_app.othermodels')
     410        self.assertEqual(mod.__name__, 'model_app.othermodels')
     411        self.assertEqual(app.__class__.__bases__, (MyApp,))
     412        self.assertEqual(app._meta.models_path, 'model_app.othermodels')
     413        self.assertEqual(app._meta.db_prefix, 'nomodel_app')
     414        self.assertEqual(app._meta.verbose_name, 'model_app')
     415
     416    def test_with_multiple_inheritance(self):
     417        from model_app.app import MyOtherApp
     418        from django.apps import App
     419        mod = cache.load_app('model_app.app.MySecondApp')
     420        app = cache.loaded_apps[0]
     421        self.assertEqual(app._meta.name, 'model_app')
     422        self.assertEqual(app._meta.models_module.__name__, 'model_app.models')
     423        self.assertEqual(mod.__name__, 'model_app.models')
     424        self.assertEqual(app.__class__.__bases__, (MyOtherApp,))
     425        self.assertEqual(app._meta.models_path, 'model_app.models')
     426        self.assertEqual(app._meta.db_prefix, 'nomodel_app')
     427        self.assertEqual(app._meta.verbose_name, 'model_app')
     428
     429    def test_with_complicated_inheritance(self):
     430        from model_app.app import MySecondApp, YetAnotherApp
     431        from django.apps import App
     432        mod = cache.load_app('model_app.app.MyThirdApp')
     433        app = cache.loaded_apps[0]
     434        self.assertEqual(app._meta.name, 'model_app')
     435        self.assertEqual(app._meta.models_module.__name__, 'model_app.yetanother')
     436        self.assertEqual(mod.__name__, 'model_app.yetanother')
     437        self.assertEqual(app.__class__.__bases__, (YetAnotherApp, MySecondApp))
     438        self.assertEqual(app._meta.models_path, 'model_app.yetanother')
     439        self.assertEqual(app._meta.db_prefix, 'nomodel_app')
     440        self.assertEqual(app._meta.verbose_name, 'model_app')
     441
     442    def test_with_custom_models(self):
     443        """
     444        Test that custom models are imported correctly, if the App specifies
     445        an models_path attribute
     446        """
     447        from model_app.app import MyApp
     448        mod = cache.load_app('model_app.app.MyApp', can_postpone=False)
     449        app = cache.loaded_apps[0]
     450        self.assertEqual(app._meta.models_module.__name__, 'model_app.othermodels')
     451        self.assertTrue(isinstance(app, MyApp))
     452        self.assertEqual(mod.__name__, 'model_app.othermodels')
     453
     454    def test_without_models(self):
     455        """
     456        Test that an app instance is created even when there are
     457        no models provided
     458        """
     459        mod = cache.load_app('nomodel_app')
     460        app = cache.loaded_apps[0]
     461        self.assertEqual(len(cache.loaded_apps), 1)
     462        self.assertEqual(app._meta.name, 'nomodel_app')
     463        self.assertEqual(mod, None)
     464
     465    def test_loading_the_same_app_twice(self):
     466        """
     467        Test that loading the same app twice results in only one app instance
     468        being created
     469        """
     470        mod = cache.load_app('model_app')
     471        mod2 = cache.load_app('model_app')
     472        self.assertEqual(len(cache.loaded_apps), 1)
     473        self.assertEqual(mod.__name__, 'model_app.models')
     474        self.assertEqual(mod2.__name__, 'model_app.models')
     475
     476    def test_importerror(self):
     477        """
     478        Test that an ImportError exception is raised if a package cannot
     479        be imported
     480        """
     481        self.assertRaises(ImportError, cache.load_app, 'garageland')
     482
     483
     484class RegisterModelsTests(AppCacheTestCase):
     485    """Tests for the register_models function"""
     486
     487    def test_seeded_cache(self):
     488        """
     489        Test that the models are attached to the correct app instance
     490        in a seeded cache
     491        """
     492        settings.INSTALLED_APPS = ('model_app',)
     493        cache._populate()
     494        self.assertTrue(cache.app_cache_ready())
     495        app_models = cache.loaded_apps[0]._meta.models.values()
     496        self.assertEqual(len(app_models), 1)
     497        self.assertEqual(app_models[0].__name__, 'Person')
     498
     499    def test_seeded_cache_invalid_app(self):
     500        """
     501        Test that registering models with an app that doesn't have an app
     502        instance works
     503        """
     504        settings.INSTALLED_APPS = ('model_app',)
     505        cache._populate()
     506        self.assertTrue(cache.app_cache_ready())
     507        from model_app.models import Person
     508        cache.register_models('model_app_NONEXISTENT', *(Person,))
     509        self.assertEquals(cache.app_models['model_app_NONEXISTENT']['person'], Person)
     510
     511    def test_unseeded_cache(self):
     512        """
     513        Test that models can be registered with an unseeded cache
     514        """
     515        from model_app.models import Person
     516        self.assertFalse(cache.app_cache_ready())
     517        self.assertEquals(cache.app_models['model_app']['person'], Person)
     518
     519
     520class FindAppTests(AppCacheTestCase):
     521    """Tests for the find_app function"""
     522
     523    def test_seeded(self):
     524        """
     525        Test that the correct app is returned when the cache is seeded
     526        """
     527        from django.apps import App
     528        settings.INSTALLED_APPS = ('model_app',)
     529        cache._populate()
     530        self.assertTrue(cache.app_cache_ready())
     531        app = cache.find_app('model_app')
     532        self.assertEquals(app._meta.name, 'model_app')
     533        self.assertTrue(isinstance(app, App))
     534        self.assertEquals(app.__repr__(), '<App: model_app>')
     535
     536    def test_seeded_invalid(self):
     537        """
     538        Test that None is returned if an app could not be found
     539        """
     540        settings.INSTALLED_APPS = ('model_app',)
     541        cache._populate()
     542        self.assertTrue(cache.app_cache_ready())
     543        app = cache.find_app('model_app_NOTVALID')
     544        self.assertEquals(app, None)
     545
     546    def test_unseeded(self):
     547        """
     548        Test that the correct app is returned when the cache is unseeded
     549        """
     550        from django.apps import App
     551        cache.load_app('model_app')
     552        self.assertFalse(cache.app_cache_ready())
     553        app = cache.find_app('model_app')
     554        self.assertEquals(app._meta.name, 'model_app')
     555        self.assertTrue(isinstance(app, App))
     556
     557    def test_option_override(self):
     558        """
     559        Tests that options of the app can be overridden in the settings
     560        """
     561        settings.INSTALLED_APPS = (
     562            ('django.contrib.admin', {
     563                'spam': 'spam',
     564            }),
     565            ('model_app.app.MyOverrideApp', {
     566                'db_prefix': 'foobar_prefix',
     567                'eggs': 'eggs',
     568            }),
     569        )
     570        cache._populate()
     571        admin = cache.find_app('admin')
     572        self.assertRaises(AttributeError, lambda: admin._meta.spam)
     573        self.assertEquals(admin.spam, 'spam')
     574        model_app = cache.find_app('model_app')
     575        self.assertEquals(model_app._meta.db_prefix, 'foobar_prefix')
     576        self.assertEquals(model_app.eggs, 'eggs')
     577
     578    def test_conflicting_option_override(self):
     579        """
     580        Tests that when overrdiding the db_prefix option in the settings
     581        it still throws an exception
     582        """
     583        settings.INSTALLED_APPS = (
     584            'nomodel_app.app.MyApp',
     585            ('model_app.app.MyOtherApp', {
     586                'db_prefix': 'nomodel_app',
     587            }),
     588        )
     589        self.assertRaises(ImproperlyConfigured, cache._populate)
     590
     591
     592class SignalTests(AppCacheTestCase):
     593    """Tests for the signals"""
     594
     595    def setUp(self):
     596        super(SignalTests, self).setUp()
     597        self.signal_fired = False
     598
     599    def test_app_loaded(self):
     600        """
     601        Test the app_loaded signal
     602        """
     603        # connect the callback before the cache is initialized
     604        def app_loaded_callback(sender, app, **kwargs):
     605            self.assertEqual(app._meta.name, 'model_app')
     606            self.signal_fired = True
     607        app_loaded.connect(app_loaded_callback)
     608
     609        settings.INSTALLED_APPS = ('model_app',)
     610        cache._populate()
     611        self.assertTrue(cache.app_cache_ready())
     612        self.assertTrue(self.signal_fired)
     613
     614    def test_post_apps_loaded(self):
     615        """
     616        Test the post_apps_loaded signal
     617        """
     618        settings.INSTALLED_APPS = ('model_app', 'anothermodel_app')
     619        def callback(sender, apps, **kwargs):
     620            self.assertEqual(len(apps), 2)
     621            self.assertEqual(apps[0]._meta.name, 'model_app')
     622            self.assertEqual(apps[1]._meta.name, 'anothermodel_app')
     623            self.signal_fired = True
     624        post_apps_loaded.connect(callback)
     625        cache._populate()
     626        self.assertTrue(cache.app_cache_ready())
     627        self.assertTrue(self.signal_fired)
     628
     629
     630class EggLoadingTests(AppCacheTestCase):
     631    """Tests loading apps from eggs"""
     632
     633    def setUp(self):
     634        super(EggLoadingTests, self).setUp()
     635        self.egg_dir = '%s/eggs' % os.path.abspath(os.path.dirname(__file__))
     636        self.old_path = sys.path[:]
     637
     638    def tearDown(self):
     639        super(EggLoadingTests, self).tearDown()
     640        sys.path = self.old_path
     641
     642    def test_egg1(self):
     643        """
     644        Models module can be loaded from an app in an egg
     645        """
     646        egg_name = '%s/modelapp.egg' % self.egg_dir
     647        sys.path.append(egg_name)
     648        models = cache.load_app('app_with_models')
     649        self.assertFalse(models is None)
     650
     651    def test_egg2(self):
     652        """
     653        Loading an app from an egg that has no models returns no models
     654        (and no error)
     655        """
     656        egg_name = '%s/nomodelapp.egg' % self.egg_dir
     657        sys.path.append(egg_name)
     658        models = cache.load_app('app_no_models')
     659        self.assertTrue(models is None)
     660
     661    def test_egg3(self):
     662        """
     663        Models module can be loaded from an app located under an egg's
     664        top-level package
     665        """
     666        egg_name = '%s/omelet.egg' % self.egg_dir
     667        sys.path.append(egg_name)
     668        models = cache.load_app('omelet.app_with_models')
     669        self.assertFalse(models is None)
     670
     671    def test_egg4(self):
     672        """
     673        Loading an app with no models from under the top-level egg package
     674        generates no error
     675        """
     676        egg_name = '%s/omelet.egg' % self.egg_dir
     677        sys.path.append(egg_name)
     678        models = cache.load_app('omelet.app_no_models')
     679        self.assertTrue(models is None)
     680
     681    def test_egg5(self):
     682        """
     683        Loading an app from an egg that has an import error in its models
     684        module raises that error
     685        """
     686        egg_name = '%s/brokenapp.egg' % self.egg_dir
     687        sys.path.append(egg_name)
     688        self.assertRaises(ImportError, cache.load_app, 'broken_app')
     689        try:
     690            cache.load_app('broken_app')
     691        except ImportError, e:
     692            # Make sure the message is indicating the actual
     693            # problem in the broken app.
     694            self.assertTrue("modelz" in e.args[0])
     695
     696if __name__ == '__main__':
     697    unittest.main()
  • deleted file tests/regressiontests/app_loading/not_installed/models.py

    diff --git a/tests/regressiontests/app_loading/eggs/brokenapp.egg b/tests/regressiontests/app_loading/eggs/brokenapp.egg
    deleted file mode 100755
    index 8aca671..0000000
    Binary files a/tests/regressiontests/app_loading/eggs/brokenapp.egg and /dev/null differ
    diff --git a/tests/regressiontests/app_loading/eggs/modelapp.egg b/tests/regressiontests/app_loading/eggs/modelapp.egg
    deleted file mode 100755
    index c2370b5..0000000
    Binary files a/tests/regressiontests/app_loading/eggs/modelapp.egg and /dev/null differ
    diff --git a/tests/regressiontests/app_loading/eggs/nomodelapp.egg b/tests/regressiontests/app_loading/eggs/nomodelapp.egg
    deleted file mode 100755
    index 5b8d217..0000000
    Binary files a/tests/regressiontests/app_loading/eggs/nomodelapp.egg and /dev/null differ
    diff --git a/tests/regressiontests/app_loading/eggs/omelet.egg b/tests/regressiontests/app_loading/eggs/omelet.egg
    deleted file mode 100755
    index bd1c687..0000000
    Binary files a/tests/regressiontests/app_loading/eggs/omelet.egg and /dev/null differ
    diff --git a/tests/regressiontests/app_loading/not_installed/__init__.py b/tests/regressiontests/app_loading/not_installed/__init__.py
    deleted file mode 100644
    index e69de29..0000000
    diff --git a/tests/regressiontests/app_loading/not_installed/models.py b/tests/regressiontests/app_loading/not_installed/models.py
    deleted file mode 100644
    index 1e4b598..0000000
    + -  
    1 from django.db import models
    2 
    3 
    4 class NotInstalledModel(models.Model):
    5     pass
    6 
    7 
    8 class RelatedModel(models.Model):
    9     not_installed = models.ForeignKey(NotInstalledModel)
    10 
    11 
    12 class M2MRelatedModel(models.Model):
    13     not_installed = models.ManyToManyField(NotInstalledModel)
  • tests/regressiontests/app_loading/tests.py

    diff --git a/tests/regressiontests/app_loading/tests.py b/tests/regressiontests/app_loading/tests.py
    index 749f24a..5378a66 100644
    a b  
    1 import copy
    21import os
    32import sys
    43import time
    54
    65from django.conf import Settings
    7 from django.db.models.loading import cache, load_app, get_model, get_models
    86from django.utils.unittest import TestCase
    97
    108
    class InstalledAppsGlobbingTest(TestCase):  
    2321        if hasattr(time, "tzset") and self.OLD_TZ:
    2422            os.environ["TZ"] = self.OLD_TZ
    2523            time.tzset()
    26 
    27 
    28 class EggLoadingTest(TestCase):
    29 
    30     def setUp(self):
    31         self.old_path = sys.path[:]
    32         self.egg_dir = '%s/eggs' % os.path.dirname(__file__)
    33 
    34         # This test adds dummy applications to the app cache. These
    35         # need to be removed in order to prevent bad interactions
    36         # with the flush operation in other tests.
    37         self.old_app_models = copy.deepcopy(cache.app_models)
    38         self.old_app_store = copy.deepcopy(cache.app_store)
    39 
    40     def tearDown(self):
    41         sys.path = self.old_path
    42         cache.app_models = self.old_app_models
    43         cache.app_store = self.old_app_store
    44 
    45     def test_egg1(self):
    46         """Models module can be loaded from an app in an egg"""
    47         egg_name = '%s/modelapp.egg' % self.egg_dir
    48         sys.path.append(egg_name)
    49         models = load_app('app_with_models')
    50         self.assertFalse(models is None)
    51 
    52     def test_egg2(self):
    53         """Loading an app from an egg that has no models returns no models (and no error)"""
    54         egg_name = '%s/nomodelapp.egg' % self.egg_dir
    55         sys.path.append(egg_name)
    56         models = load_app('app_no_models')
    57         self.assertTrue(models is None)
    58 
    59     def test_egg3(self):
    60         """Models module can be loaded from an app located under an egg's top-level package"""
    61         egg_name = '%s/omelet.egg' % self.egg_dir
    62         sys.path.append(egg_name)
    63         models = load_app('omelet.app_with_models')
    64         self.assertFalse(models is None)
    65 
    66     def test_egg4(self):
    67         """Loading an app with no models from under the top-level egg package generates no error"""
    68         egg_name = '%s/omelet.egg' % self.egg_dir
    69         sys.path.append(egg_name)
    70         models = load_app('omelet.app_no_models')
    71         self.assertTrue(models is None)
    72 
    73     def test_egg5(self):
    74         """Loading an app from an egg that has an import error in its models module raises that error"""
    75         egg_name = '%s/brokenapp.egg' % self.egg_dir
    76         sys.path.append(egg_name)
    77         self.assertRaises(ImportError, load_app, 'broken_app')
    78         try:
    79             load_app('broken_app')
    80         except ImportError, e:
    81             # Make sure the message is indicating the actual
    82             # problem in the broken app.
    83             self.assertTrue("modelz" in e.args[0])
    84 
    85 
    86 class GetModelsTest(TestCase):
    87     def setUp(self):
    88         from .not_installed import models
    89         self.not_installed_module = models
    90 
    91 
    92     def test_get_model_only_returns_installed_models(self):
    93         self.assertEqual(
    94             get_model("not_installed", "NotInstalledModel"), None)
    95 
    96 
    97     def test_get_model_with_not_installed(self):
    98         self.assertEqual(
    99             get_model(
    100                 "not_installed", "NotInstalledModel", only_installed=False),
    101             self.not_installed_module.NotInstalledModel)
    102 
    103 
    104     def test_get_models_only_returns_installed_models(self):
    105         self.assertFalse(
    106             "NotInstalledModel" in
    107             [m.__name__ for m in get_models()])
    108 
    109 
    110     def test_get_models_with_app_label_only_returns_installed_models(self):
    111         self.assertEqual(get_models(self.not_installed_module), [])
    112 
    113 
    114     def test_get_models_with_not_installed(self):
    115         self.assertTrue(
    116             "NotInstalledModel" in [
    117                 m.__name__ for m in get_models(only_installed=False)])
    118 
    119 
    120 class NotInstalledModelsTest(TestCase):
    121     def test_related_not_installed_model(self):
    122         from .not_installed.models import NotInstalledModel
    123         self.assertEqual(
    124             set(NotInstalledModel._meta.get_all_field_names()),
    125             set(["id", "relatedmodel", "m2mrelatedmodel"]))
  • tests/regressiontests/i18n/tests.py

    diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
    index 0b955ad..5350b2b 100644
    a b import pickle  
    77from threading import local
    88
    99from django.conf import settings
     10from django.apps import cache
    1011from django.template import Template, Context
    1112from django.test import TestCase, RequestFactory
    1213from django.utils.formats import (get_format, date_format, time_format,
    class ResolutionOrderI18NTests(TestCase):  
    618619        self.assertTrue(msgstr in result, ("The string '%s' isn't in the "
    619620            "translation of '%s'; the actual result is '%s'." % (msgstr, msgid, result)))
    620621
     622class MockedApp(object):
     623    class Meta:
     624        def path(self):
     625            return os.path.join(
     626                os.path.dirname(os.path.abspath(__file__)), 'resolution')
     627    _meta = Meta()
     628
    621629class AppResolutionOrderI18NTests(ResolutionOrderI18NTests):
    622630
    623631    def setUp(self):
    624         self.old_installed_apps = settings.INSTALLED_APPS
    625         settings.INSTALLED_APPS = ['regressiontests.i18n.resolution'] + list(settings.INSTALLED_APPS)
     632        self.old_loaded_apps = cache.loaded_apps
     633        cache.loaded_apps = [MockedApp()] + cache.loaded_apps
    626634        super(AppResolutionOrderI18NTests, self).setUp()
    627635
    628636    def tearDown(self):
    629         settings.INSTALLED_APPS = self.old_installed_apps
     637        cache.loaded_apps = self.old_loaded_apps
    630638        super(AppResolutionOrderI18NTests, self).tearDown()
    631639
    632640    def test_app_translation(self):
  • tests/regressiontests/staticfiles_tests/tests.py

    diff --git a/tests/regressiontests/staticfiles_tests/tests.py b/tests/regressiontests/staticfiles_tests/tests.py
    index 4056948..4c14fb8 100644
    a b import sys  
    88import tempfile
    99from StringIO import StringIO
    1010
    11 from django.template import loader, Context
    1211from django.conf import settings
    1312from django.core.exceptions import ImproperlyConfigured
    1413from django.core.files.storage import default_storage
    1514from django.core.management import call_command
     15from django.template import loader, Context
    1616from django.test import TestCase
    1717from django.test.utils import override_settings
    1818from django.utils.encoding import smart_unicode
  • tests/regressiontests/templates/loaders.py

    diff --git a/tests/regressiontests/templates/loaders.py b/tests/regressiontests/templates/loaders.py
    index c2ae0bd..d5738be 100644
    a b Note: This test requires setuptools!  
    55"""
    66
    77from django.conf import settings
     8from django.apps import cache
    89
    910if __name__ == '__main__':
    1011    settings.configure()
    def create_egg(name, resources):  
    5455    egg._resources = resources
    5556    sys.modules[name] = egg
    5657
     58class MockedApp(object):
     59    def __init__(self, name):
     60        self.name = name
     61    @property
     62    def _meta(self):
     63        return self
    5764
    5865class EggLoaderTest(unittest.TestCase):
    5966    def setUp(self):
    class EggLoaderTest(unittest.TestCase):  
    6471            os.path.normcase('templates/y.html') : StringIO.StringIO("y"),
    6572            os.path.normcase('templates/x.txt') : StringIO.StringIO("x"),
    6673        })
    67         self._old_installed_apps = settings.INSTALLED_APPS
    68         settings.INSTALLED_APPS = []
     74        self.old_loaded_apps = cache.loaded_apps
    6975
    7076    def tearDown(self):
    71         settings.INSTALLED_APPS = self._old_installed_apps
     77        cache.loaded_apps = self.old_loaded_apps
    7278
    7379    def test_empty(self):
    7480        "Loading any template on an empty egg should fail"
    75         settings.INSTALLED_APPS = ['egg_empty']
     81        cache.loaded_apps = [MockedApp('egg_empty')]
    7682        egg_loader = EggLoader()
    7783        self.assertRaises(TemplateDoesNotExist, egg_loader.load_template_source, "not-existing.html")
    7884
    7985    def test_non_existing(self):
    8086        "Template loading fails if the template is not in the egg"
    81         settings.INSTALLED_APPS = ['egg_1']
     87        cache.loaded_apps = [MockedApp('egg_1')]
    8288        egg_loader = EggLoader()
    8389        self.assertRaises(TemplateDoesNotExist, egg_loader.load_template_source, "not-existing.html")
    8490
    8591    def test_existing(self):
    8692        "A template can be loaded from an egg"
    87         settings.INSTALLED_APPS = ['egg_1']
     93        cache.loaded_apps = [MockedApp('egg_1')]
    8894        egg_loader = EggLoader()
    8995        contents, template_name = egg_loader.load_template_source("y.html")
    9096        self.assertEqual(contents, "y")
    9197        self.assertEqual(template_name, "egg:egg_1:templates/y.html")
    9298
    9399    def test_not_installed(self):
    94         "Loading an existent template from an egg not included in INSTALLED_APPS should fail"
    95         settings.INSTALLED_APPS = []
     100        "Loading an existent template from an egg not included in loaded_apps should fail"
     101        cache.loaded_apps = []
    96102        egg_loader = EggLoader()
    97103        self.assertRaises(TemplateDoesNotExist, egg_loader.load_template_source, "y.html")
    98104
  • tests/regressiontests/templates/tests.py

    diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
    index 1d1efe5..2ee883c 100644
    a b  
    11# -*- coding: utf-8 -*-
     2from django.apps import cache
    23from django.conf import settings
    34
    45if __name__ == '__main__':
    class Templates(unittest.TestCase):  
    16131614            'static-statictag02': ('{% load static %}{% static base_css %}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')),
    16141615        }
    16151616
     1617class MockedApp(object):
     1618    def __init__(self, name):
     1619        self.name = name
     1620    @property
     1621    def _meta(self):
     1622        return self
     1623
    16161624class TemplateTagLoading(unittest.TestCase):
    16171625
    16181626    def setUp(self):
    16191627        self.old_path = sys.path[:]
    1620         self.old_apps = settings.INSTALLED_APPS
     1628        self.old_loaded_apps = cache.loaded_apps
    16211629        self.egg_dir = '%s/eggs' % os.path.dirname(__file__)
    16221630        self.old_tag_modules = template_base.templatetags_modules
    16231631        template_base.templatetags_modules = []
    16241632
    16251633    def tearDown(self):
    1626         settings.INSTALLED_APPS = self.old_apps
     1634        cache.loaded_apps = self.old_loaded_apps
    16271635        sys.path = self.old_path
    16281636        template_base.templatetags_modules = self.old_tag_modules
    16291637
    class TemplateTagLoading(unittest.TestCase):  
    16401648        ttext = "{% load broken_egg %}"
    16411649        egg_name = '%s/tagsegg.egg' % self.egg_dir
    16421650        sys.path.append(egg_name)
    1643         settings.INSTALLED_APPS = ('tagsegg',)
     1651        cache.loaded_apps = (MockedApp('tagsegg'),)
    16441652        self.assertRaises(template.TemplateSyntaxError, template.Template, ttext)
    16451653        try:
    16461654            template.Template(ttext)
    class TemplateTagLoading(unittest.TestCase):  
    16521660        ttext = "{% load working_egg %}"
    16531661        egg_name = '%s/tagsegg.egg' % self.egg_dir
    16541662        sys.path.append(egg_name)
    1655         settings.INSTALLED_APPS = ('tagsegg',)
     1663        cache.loaded_apps = (MockedApp('tagsegg'),)
    16561664        t = template.Template(ttext)
    16571665
    16581666
  • tests/runtests.py

    diff --git a/tests/runtests.py b/tests/runtests.py
    index ba66d2a..b955b6b 100755
    a b def setup(verbosity, test_labels):  
    136136    # in our tests.
    137137    settings.MANAGERS = ("admin@djangoproject.com",)
    138138
    139     # Load all the ALWAYS_INSTALLED_APPS.
    140     # (This import statement is intentionally delayed until after we
    141     # access settings because of the USE_I18N dependency.)
    142     from django.db.models.loading import get_apps, load_app
    143     get_apps()
     139    # This import statement is intentionally delayed until after we
     140    # access settings because of the USE_I18N dependency.
     141    from django.db.models.loading import load_app
    144142
    145143    # Load all the test model apps.
    146144    test_labels_set = set([label.split('.')[0] for label in test_labels])
Back to Top