Ticket #3591: app-loading.diff
File app-loading.diff, 100.8 KB (added by , 13 years ago) |
---|
-
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
- + 1 from django.apps.base import App 2 from 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 10 cache = AppCache() 11 12 # These methods were always module level, so are kept that way for backwards 13 # compatibility. 14 find_app = cache.find_app 15 get_apps = cache.get_apps 16 get_app = cache.get_app 17 get_app_errors = cache.get_app_errors 18 get_models = cache.get_models 19 get_model = cache.get_model 20 register_models = cache.register_models 21 load_app = cache.load_app 22 app_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
- + 1 import re 2 import sys 3 4 from django.apps.options import AppOptions, DEFAULT_NAMES 5 6 module_name_re = re.compile(r'_([a-z])') 7 8 9 class 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 44 class 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
- + 1 import sys 2 import os 3 import threading 4 5 from django.conf import settings 6 from django.core.exceptions import ImproperlyConfigured 7 from django.utils.datastructures import SortedDict 8 from django.utils.importlib import import_module 9 from django.utils.module_loading import module_has_submodule 10 11 from django.apps.base import App 12 from django.apps.signals import app_loaded, post_apps_loaded 13 14 15 def _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 36 class 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
- + 1 import re 2 import os 3 4 from django.utils.datastructures import SortedDict 5 from django.utils.importlib import import_module 6 from django.utils.text import get_verbose_name 7 8 DEFAULT_NAMES = ('verbose_name', 'db_prefix', 'models_path') 9 10 11 class 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
- + 1 from django.dispatch import Signal 2 3 # Sent when an app is loaded by the app cache 4 app_loaded = Signal(providing_args=["app"]) 5 6 # Sent when the app cache loads the apps 7 post_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 1 1 # ACTION_CHECKBOX_NAME is unused, but should stay since its import from here 2 2 # has been referenced in documentation. 3 from django.apps import cache 3 4 from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME 4 5 from django.contrib.admin.options import ModelAdmin, HORIZONTAL, VERTICAL 5 6 from django.contrib.admin.options import StackedInline, TabularInline … … from django.contrib.admin.filters import (ListFilter, SimpleListFilter, 8 9 FieldListFilter, BooleanFieldListFilter, RelatedFieldListFilter, 9 10 ChoicesFieldListFilter, DateFieldListFilter, AllValuesFieldListFilter) 10 11 11 12 12 def autodiscover(): 13 13 """ 14 14 Auto-discover INSTALLED_APPS admin.py modules and fail silently when … … def autodiscover(): 21 21 from django.utils.importlib import import_module 22 22 from django.utils.module_loading import module_has_submodule 23 23 24 for app in settings.INSTALLED_APPS: 25 mod = import_module(app) 24 for app in cache.loaded_apps: 26 25 # Attempt to import the app's admin module. 27 26 try: 28 27 before_import_registry = copy.copy(site._registry) 29 import_module('%s.admin' % app )28 import_module('%s.admin' % app._meta.name) 30 29 except: 31 30 # Reset the model registry to the state before the last import as 32 31 # this import will have to reoccur on the next request and this … … def autodiscover(): 37 36 # Decide whether to bubble up this error. If the app just 38 37 # doesn't have an admin module, we can ignore the error 39 38 # 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'): 41 40 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 1 1 from functools import update_wrapper, partial 2 from django import forms2 from django import apps, forms, template 3 3 from django.forms.formsets import all_valid 4 4 from django.forms.models import (modelform_factory, modelformset_factory, 5 5 inlineformset_factory, BaseInlineFormSet) … … class ModelAdmin(BaseModelAdmin): 968 968 'media': mark_safe(media), 969 969 'inline_admin_formsets': inline_admin_formsets, 970 970 'errors': helpers.AdminErrorList(form, formsets), 971 'app_label': opts.app_label,971 'app_label': apps.find_app(opts.app_label)._meta.verbose_name, 972 972 } 973 973 context.update(extra_context or {}) 974 974 return self.render_change_form(request, context, form_url=form_url, add=True) … … class ModelAdmin(BaseModelAdmin): 1058 1058 'media': mark_safe(media), 1059 1059 'inline_admin_formsets': inline_admin_formsets, 1060 1060 'errors': helpers.AdminErrorList(form, formsets), 1061 'app_label': opts.app_label,1061 'app_label': apps.find_app(opts.app_label)._meta.verbose_name, 1062 1062 } 1063 1063 context.update(extra_context or {}) 1064 1064 return self.render_change_form(request, context, change=True, obj=obj) … … class ModelAdmin(BaseModelAdmin): 1199 1199 'cl': cl, 1200 1200 'media': media, 1201 1201 'has_add_permission': self.has_add_permission(request), 1202 'app_label': app _label,1202 'app_label': apps.find_app(app_label)._meta.verbose_name, 1203 1203 'action_form': action_form, 1204 1204 'actions_on_top': self.actions_on_top, 1205 1205 'actions_on_bottom': self.actions_on_bottom, … … class ModelAdmin(BaseModelAdmin): 1263 1263 "perms_lacking": perms_needed, 1264 1264 "protected": protected, 1265 1265 "opts": opts, 1266 "app_label": app _label,1266 "app_label": apps.find_app(app_label)._meta.verbose_name, 1267 1267 } 1268 1268 context.update(extra_context or {}) 1269 1269 … … class ModelAdmin(BaseModelAdmin): 1290 1290 'action_list': action_list, 1291 1291 'module_name': capfirst(force_unicode(opts.verbose_name_plural)), 1292 1292 'object': obj, 1293 'app_label': app _label,1293 'app_label': apps.find_app(app_label)._meta.verbose_name, 1294 1294 } 1295 1295 context.update(extra_context or {}) 1296 1296 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 1 1 from functools import update_wrapper 2 from django import http 2 3 from django import apps, http 3 4 from django.contrib.admin import ModelAdmin, actions 4 5 from django.contrib.admin.forms import AdminAuthenticationForm 5 6 from django.contrib.auth import REDIRECT_FIELD_NAME … … class AdminSite(object): 348 349 app_dict[app_label]['models'].append(model_dict) 349 350 else: 350 351 app_dict[app_label] = { 351 'name': app _label.title(),352 'name': apps.find_app(app_label)._meta.verbose_name, 352 353 'app_url': app_label + '/', 353 354 'has_module_perms': has_module_perms, 354 355 'models': [model_dict], … … class AdminSite(object): 375 376 user = request.user 376 377 has_module_perms = user.has_module_perms(app_label) 377 378 app_dict = {} 379 app = apps.find_app(app_label) 378 380 for model, model_admin in self._registry.items(): 379 381 if app_label == model._meta.app_label: 380 382 if has_module_perms: … … class AdminSite(object): 395 397 # something to display, add in the necessary meta 396 398 # information. 397 399 app_dict = { 398 'name': app _label.title(),400 'name': app._meta.verbose_name, 399 401 'app_url': '', 400 402 'has_module_perms': has_module_perms, 401 403 'models': [model_dict], … … class AdminSite(object): 405 407 # Sort the models alphabetically within each app. 406 408 app_dict['models'].sort(key=lambda x: x['name']) 407 409 context = { 408 'title': _('%s administration') % capfirst(app_label),410 'title': _('%s administration') % app._meta.verbose_name, 409 411 'app_list': [app_dict], 410 412 } 411 413 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
- + 1 from django import apps 2 from django.utils.translation import ugettext_lazy as _ 3 4 class 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 1 from django.apps import cache, get_apps, get_models 1 2 from django.contrib.contenttypes.models import ContentType 2 from django.db.models import get_apps, get_models,signals3 from django.db.models import signals 3 4 from django.utils.encoding import smart_unicode 4 5 5 6 def update_contenttypes(app, created_models, verbosity=2, **kwargs): … … def update_contenttypes(app, created_models, verbosity=2, **kwargs): 7 8 Creates content types for models in the given app, removing any model 8 9 entries that no longer have a matching model class. 9 10 """ 11 app_cls = cache.find_app_by_models_module(app) 10 12 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)) 12 14 app_models = get_models(app) 13 15 if not app_models: 14 16 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 1 1 import os 2 from django.apps import cache 2 3 from django.conf import settings 3 4 from django.core.exceptions import ImproperlyConfigured 4 5 from django.core.files.storage import default_storage, Storage, FileSystemStorage … … class AppDirectoriesFinder(BaseFinder): 113 114 """ 114 115 storage_class = AppStaticStorage 115 116 116 def __init__(self, apps=None,*args, **kwargs):117 def __init__(self, *args, **kwargs): 117 118 # The list of apps that are handled 118 119 self.apps = [] 119 120 # Mapping of app module paths to storage instances 120 121 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: 124 123 app_storage = self.storage_class(app) 125 124 if os.path.isdir(app_storage.location): 126 125 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): 194 194 Returns a static file storage if available in the given app. 195 195 """ 196 196 # 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) 200 198 super(AppStaticStorage, self).__init__(location, *args, **kwargs) 201 199 202 200 -
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(): 97 97 98 98 # Find the installed apps 99 99 try: 100 from django. conf import settings101 apps = settings.INSTALLED_APPS100 from django.apps import cache 101 apps = cache.loaded_apps 102 102 except (AttributeError, EnvironmentError, ImportError): 103 103 apps = [] 104 104 … … def get_commands(): 111 111 project_directory = None 112 112 113 113 # Find and load the management module for each installed app. 114 for app _namein apps:114 for app in apps: 115 115 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) 118 118 for name in find_commands(path)])) 119 119 except ImportError: 120 120 pass # No management module - ignore this app … … class ManagementUtility(object): 316 316 try: 317 317 from django.conf import settings 318 318 # 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] 320 320 except ImportError: 321 321 # Fail silently if DJANGO_SETTINGS_MODULE isn't set. The 322 322 # user will find out once they execute the command. … … def setup_environ(settings_mod, original_settings_path=None): 423 423 project_module = import_module(project_name) 424 424 sys.path.pop() 425 425 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 426 432 return project_directory 427 433 428 434 def 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 1 1 from optparse import make_option 2 2 3 from django.apps import cache 3 4 from django.conf import settings 4 5 from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS 5 6 from django.core.management import call_command … … class Command(NoArgsCommand): 29 30 30 31 # Import the 'management' module within each installed app, to register 31 32 # dispatcher events. 32 for app _name in settings.INSTALLED_APPS:33 for app in cache.loaded_apps: 33 34 try: 34 import_module(' .management', app_name)35 import_module('%s.management' % app._meta.name) 35 36 except ImportError: 36 37 pass 37 38 -
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 1 1 from optparse import make_option 2 2 import sys 3 3 4 from django.apps import cache 4 5 from django.conf import settings 5 6 from django.core.management.base import NoArgsCommand 6 7 from django.core.management.color import no_style … … class Command(NoArgsCommand): 18 19 default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. ' 19 20 'Defaults to the "default" database.'), 20 21 ) 21 help = "Create the database tables for all apps in INSTALLED_APPSwhose tables haven't already been created."22 help = "Create the database tables for all installed apps whose tables haven't already been created." 22 23 23 24 def handle_noargs(self, **options): 24 25 … … class Command(NoArgsCommand): 34 35 35 36 # Import the 'management' module within each installed app, to register 36 37 # dispatcher events. 37 for app _name in settings.INSTALLED_APPS:38 for app in cache.loaded_apps: 38 39 try: 39 import_module('.management', app _name)40 import_module('.management', app._meta.name) 40 41 except ImportError, exc: 41 42 # This is slightly hackish. We want to ignore ImportErrors 42 43 # if the "management" module itself is missing -- but we don't … … class Command(NoArgsCommand): 63 64 64 65 # Build the manifest of apps and models that are to be synchronized 65 66 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) 68 70 if router.allow_syncdb(db, m)]) 69 for app in models.get_apps()71 for app in cache.loaded_apps 70 72 ] 71 73 def model_installed(model): 72 74 opts = model._meta … … class Command(NoArgsCommand): 101 103 cursor.execute(statement) 102 104 tables.append(connection.introspection.table_name_converter(model._meta.db_table)) 103 105 104 105 106 transaction.commit_unless_managed(using=db) 106 107 107 108 # 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 1 1 import os 2 2 import re 3 3 4 from django.apps import cache, get_models 4 5 from django.conf import settings 5 6 from django.core.management.base import CommandError 6 7 from django.db import models 7 from django.db.models import get_models8 8 9 9 def sql_create(app, style, connection): 10 10 "Returns a list of the CREATE TABLE SQL statements for the given app." … … def custom_sql_for_model(model, style, connection): 182 182 def emit_post_sync_signal(created_models, verbosity, interactive, db): 183 183 # Emit the post_sync signal for every application. 184 184 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 186 187 if verbosity >= 2: 187 188 print "Running post-sync handlers for application", app_name 188 189 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): 118 118 else: 119 119 base = parent 120 120 if base is None: 121 121 raise TypeError("Proxy model '%s' has no non-abstract model base class." % name) 122 122 if (new_class._meta.local_fields or 123 123 new_class._meta.local_many_to_many): 124 124 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." 1 import warnings 2 2 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 3 from 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) 8 6 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 7 warnings.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 1 1 import re 2 2 from bisect import bisect 3 3 4 from django.apps import cache 4 5 from django.conf import settings 5 6 from django.db.models.related import RelatedObject 6 7 from django.db.models.fields.related import ManyToManyRel … … from django.db.models.loading import get_models, app_cache_ready 10 11 from django.utils.translation import activate, deactivate_all, get_language, string_concat 11 12 from django.utils.encoding import force_unicode, smart_str 12 13 from django.utils.datastructures import SortedDict 14 from django.utils.text import get_verbose_name 13 15 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()16 16 17 17 DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering', 18 18 'unique_together', 'permissions', 'get_latest_by', … … class Options(object): 59 59 from django.db.backends.util import truncate_name 60 60 61 61 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 63 64 # First, construct the default values for these options. 64 65 self.object_name = cls.__name__ 65 66 self.module_name = self.object_name.lower() … … class Options(object): 100 101 self.verbose_name_plural = string_concat(self.verbose_name, 's') 101 102 del self.meta 102 103 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 104 107 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()) 107 112 108 113 def _prepare(self, model): 109 114 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 2 2 from functools import partial 3 3 from inspect import getargspec 4 4 5 from django.apps import cache 5 6 from django.conf import settings 6 7 from django.template.context import Context, RequestContext, ContextPopException 7 8 from django.utils.importlib import import_module … … def get_templatetags_modules(): 1046 1047 if not templatetags_modules: 1047 1048 _templatetags_modules = [] 1048 1049 # 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]: 1050 1051 try: 1051 1052 templatetag_module = '%s.templatetags' % app_module 1052 1053 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. 6 6 import os 7 7 import sys 8 8 9 from django.apps import cache 9 10 from django.conf import settings 10 11 from django.core.exceptions import ImproperlyConfigured 11 12 from django.template.base import TemplateDoesNotExist … … from django.utils.importlib import import_module 16 17 # At compile time, cache the directories to search. 17 18 fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() 18 19 app_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') 20 for app in cache.loaded_apps: 21 template_dir = os.path.join(app._meta.path, 'templates') 25 22 if os.path.isdir(template_dir): 26 23 app_template_dirs.append(template_dir.decode(fs_encoding)) 27 24 -
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 1 1 # Wrapper for loading templates from eggs via pkg_resources.resource_string. 2 from django.apps import cache 2 3 3 4 try: 4 5 from pkg_resources import resource_string … … class Loader(BaseLoader): 20 21 """ 21 22 if resource_string is not None: 22 23 pkg_name = 'templates/' + template_name 23 for app in settings.INSTALLED_APPS:24 for app in cache.loaded_apps: 24 25 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: 27 28 pass 28 29 raise TemplateDoesNotExist(template_name) 29 30 -
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): 14 14 for finder in sys.meta_path: 15 15 if finder.find_module(name, package.__path__): 16 16 return True 17 # If this isn't really a package return False right away 18 if not hasattr(package, '__path__'): 19 return False 17 20 for entry in package.__path__: # No __path__, then not a package. 18 21 try: 19 22 # 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): 362 362 unescape_entities = allow_lazy(unescape_entities, unicode) 363 363 364 364 def unescape_string_literal(s): 365 r"""366 Convert quoted string literals to unquoted strings with escaped quotes and367 backslashes unquoted::365 """ 366 Converts quoted string literals to unquoted strings with escaped quotes 367 and backslashes unquoted:: 368 368 369 369 >>> unescape_string_literal('"abc"') 370 370 'abc' … … def unescape_string_literal(s): 380 380 quote = s[0] 381 381 return s[1:-1].replace(r'\%s' % quote, quote).replace(r'\\', '\\') 382 382 unescape_string_literal = allow_lazy(unescape_string_literal) 383 384 def 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: 12 12 except ImportError: 13 13 from StringIO import StringIO 14 14 15 from django.apps import cache 15 16 from django.utils.importlib import import_module 16 17 from django.utils.safestring import mark_safe, SafeData 17 18 … … def translation(language): 156 157 res.merge(t) 157 158 return res 158 159 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') 162 162 163 163 if os.path.isdir(apppath): 164 164 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 2 2 import gettext as gettext_module 3 3 4 4 from django import http 5 from django.apps import cache 5 6 from django.conf import settings 6 7 from django.utils import importlib 7 8 from django.utils.translation import check_for_language, activate, to_locale, get_language … … def javascript_catalog(request, domain='djangojs', packages=None): 186 187 packages = ['django.conf'] 187 188 if isinstance(packages, basestring): 188 189 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] 190 192 default_locale = to_locale(settings.LANGUAGE_CODE) 191 193 locale = to_locale(get_language()) 192 194 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
- + 1 from django import apps 2 3 class MyApp(apps.App): 4 5 class Meta: 6 models_path = 'model_app.othermodels' 7 8 class 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
- + 1 from django.db import models 2 3 class Job(models.Model): 4 name = models.CharField(max_length=30) 5 6 class 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 11 class 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
- + 1 from django.db import models 2 3 class 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
- + 1 from django import apps 2 3 class MyApp(apps.App): 4 5 class Meta: 6 models_path = 'model_app.othermodels' 7 8 class MyOtherApp(MyApp): 9 10 class Meta(MyApp.Meta): 11 db_prefix = 'nomodel_app' 12 13 14 class MySecondApp(MyOtherApp): 15 16 class Meta(MyOtherApp.Meta): 17 models_path = 'model_app.models' 18 19 20 class YetAnotherApp(apps.App): 21 22 class Meta: 23 models_path = 'model_app.yetanother' 24 25 26 class MyThirdApp(YetAnotherApp, MySecondApp): 27 28 class Meta(YetAnotherApp.Meta, MySecondApp.Meta): 29 pass 30 31 32 class 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
- + 1 from django.db import models 2 3 class 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
- + 1 from django.db import models 2 3 class 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
- + 1 from django import apps 2 3 class MyApp(apps.App): 4 pass 5 6 class 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
- + 1 from django.db import models 2 3 class 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
- + 1 from django import apps 2 3 class 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 2 import os 3 import sys 4 import unittest 5 import threading 6 7 from django.apps import cache 8 from django.apps.cache import _initialize 9 from django.apps.signals import app_loaded, post_apps_loaded 10 from django.conf import settings 11 from django.core.exceptions import ImproperlyConfigured 12 from django.utils.datastructures import SortedDict 13 14 # remove when tests are integrated into the django testsuite 15 settings.configure() 16 17 18 class 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 36 class 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 66 class 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 88 class 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 142 class 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 193 class 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 236 class 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 245 class 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 322 class 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 389 class 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 484 class 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 520 class 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 592 class 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 630 class 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 696 if __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 models2 3 4 class NotInstalledModel(models.Model):5 pass6 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 copy2 1 import os 3 2 import sys 4 3 import time 5 4 6 5 from django.conf import Settings 7 from django.db.models.loading import cache, load_app, get_model, get_models8 6 from django.utils.unittest import TestCase 9 7 10 8 … … class InstalledAppsGlobbingTest(TestCase): 23 21 if hasattr(time, "tzset") and self.OLD_TZ: 24 22 os.environ["TZ"] = self.OLD_TZ 25 23 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. These35 # need to be removed in order to prevent bad interactions36 # 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_path42 cache.app_models = self.old_app_models43 cache.app_store = self.old_app_store44 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_dir48 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_dir55 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_dir62 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_dir69 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_dir76 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 actual82 # 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 models89 self.not_installed_module = models90 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" in107 [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 NotInstalledModel123 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 7 7 from threading import local 8 8 9 9 from django.conf import settings 10 from django.apps import cache 10 11 from django.template import Template, Context 11 12 from django.test import TestCase, RequestFactory 12 13 from django.utils.formats import (get_format, date_format, time_format, … … class ResolutionOrderI18NTests(TestCase): 618 619 self.assertTrue(msgstr in result, ("The string '%s' isn't in the " 619 620 "translation of '%s'; the actual result is '%s'." % (msgstr, msgid, result))) 620 621 622 class 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 621 629 class AppResolutionOrderI18NTests(ResolutionOrderI18NTests): 622 630 623 631 def setUp(self): 624 self.old_ installed_apps = settings.INSTALLED_APPS625 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 626 634 super(AppResolutionOrderI18NTests, self).setUp() 627 635 628 636 def tearDown(self): 629 settings.INSTALLED_APPS = self.old_installed_apps637 cache.loaded_apps = self.old_loaded_apps 630 638 super(AppResolutionOrderI18NTests, self).tearDown() 631 639 632 640 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 8 8 import tempfile 9 9 from StringIO import StringIO 10 10 11 from django.template import loader, Context12 11 from django.conf import settings 13 12 from django.core.exceptions import ImproperlyConfigured 14 13 from django.core.files.storage import default_storage 15 14 from django.core.management import call_command 15 from django.template import loader, Context 16 16 from django.test import TestCase 17 17 from django.test.utils import override_settings 18 18 from 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! 5 5 """ 6 6 7 7 from django.conf import settings 8 from django.apps import cache 8 9 9 10 if __name__ == '__main__': 10 11 settings.configure() … … def create_egg(name, resources): 54 55 egg._resources = resources 55 56 sys.modules[name] = egg 56 57 58 class MockedApp(object): 59 def __init__(self, name): 60 self.name = name 61 @property 62 def _meta(self): 63 return self 57 64 58 65 class EggLoaderTest(unittest.TestCase): 59 66 def setUp(self): … … class EggLoaderTest(unittest.TestCase): 64 71 os.path.normcase('templates/y.html') : StringIO.StringIO("y"), 65 72 os.path.normcase('templates/x.txt') : StringIO.StringIO("x"), 66 73 }) 67 self._old_installed_apps = settings.INSTALLED_APPS 68 settings.INSTALLED_APPS = [] 74 self.old_loaded_apps = cache.loaded_apps 69 75 70 76 def tearDown(self): 71 settings.INSTALLED_APPS = self._old_installed_apps77 cache.loaded_apps = self.old_loaded_apps 72 78 73 79 def test_empty(self): 74 80 "Loading any template on an empty egg should fail" 75 settings.INSTALLED_APPS = ['egg_empty']81 cache.loaded_apps = [MockedApp('egg_empty')] 76 82 egg_loader = EggLoader() 77 83 self.assertRaises(TemplateDoesNotExist, egg_loader.load_template_source, "not-existing.html") 78 84 79 85 def test_non_existing(self): 80 86 "Template loading fails if the template is not in the egg" 81 settings.INSTALLED_APPS = ['egg_1']87 cache.loaded_apps = [MockedApp('egg_1')] 82 88 egg_loader = EggLoader() 83 89 self.assertRaises(TemplateDoesNotExist, egg_loader.load_template_source, "not-existing.html") 84 90 85 91 def test_existing(self): 86 92 "A template can be loaded from an egg" 87 settings.INSTALLED_APPS = ['egg_1']93 cache.loaded_apps = [MockedApp('egg_1')] 88 94 egg_loader = EggLoader() 89 95 contents, template_name = egg_loader.load_template_source("y.html") 90 96 self.assertEqual(contents, "y") 91 97 self.assertEqual(template_name, "egg:egg_1:templates/y.html") 92 98 93 99 def test_not_installed(self): 94 "Loading an existent template from an egg not included in INSTALLED_APPSshould fail"95 settings.INSTALLED_APPS= []100 "Loading an existent template from an egg not included in loaded_apps should fail" 101 cache.loaded_apps = [] 96 102 egg_loader = EggLoader() 97 103 self.assertRaises(TemplateDoesNotExist, egg_loader.load_template_source, "y.html") 98 104 -
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 1 1 # -*- coding: utf-8 -*- 2 from django.apps import cache 2 3 from django.conf import settings 3 4 4 5 if __name__ == '__main__': … … class Templates(unittest.TestCase): 1613 1614 'static-statictag02': ('{% load static %}{% static base_css %}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')), 1614 1615 } 1615 1616 1617 class MockedApp(object): 1618 def __init__(self, name): 1619 self.name = name 1620 @property 1621 def _meta(self): 1622 return self 1623 1616 1624 class TemplateTagLoading(unittest.TestCase): 1617 1625 1618 1626 def setUp(self): 1619 1627 self.old_path = sys.path[:] 1620 self.old_ apps = settings.INSTALLED_APPS1628 self.old_loaded_apps = cache.loaded_apps 1621 1629 self.egg_dir = '%s/eggs' % os.path.dirname(__file__) 1622 1630 self.old_tag_modules = template_base.templatetags_modules 1623 1631 template_base.templatetags_modules = [] 1624 1632 1625 1633 def tearDown(self): 1626 settings.INSTALLED_APPS = self.old_apps1634 cache.loaded_apps = self.old_loaded_apps 1627 1635 sys.path = self.old_path 1628 1636 template_base.templatetags_modules = self.old_tag_modules 1629 1637 … … class TemplateTagLoading(unittest.TestCase): 1640 1648 ttext = "{% load broken_egg %}" 1641 1649 egg_name = '%s/tagsegg.egg' % self.egg_dir 1642 1650 sys.path.append(egg_name) 1643 settings.INSTALLED_APPS = ('tagsegg',)1651 cache.loaded_apps = (MockedApp('tagsegg'),) 1644 1652 self.assertRaises(template.TemplateSyntaxError, template.Template, ttext) 1645 1653 try: 1646 1654 template.Template(ttext) … … class TemplateTagLoading(unittest.TestCase): 1652 1660 ttext = "{% load working_egg %}" 1653 1661 egg_name = '%s/tagsegg.egg' % self.egg_dir 1654 1662 sys.path.append(egg_name) 1655 settings.INSTALLED_APPS = ('tagsegg',)1663 cache.loaded_apps = (MockedApp('tagsegg'),) 1656 1664 t = template.Template(ttext) 1657 1665 1658 1666 -
tests/runtests.py
diff --git a/tests/runtests.py b/tests/runtests.py index ba66d2a..b955b6b 100755
a b def setup(verbosity, test_labels): 136 136 # in our tests. 137 137 settings.MANAGERS = ("admin@djangoproject.com",) 138 138 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 144 142 145 143 # Load all the test model apps. 146 144 test_labels_set = set([label.split('.')[0] for label in test_labels])