summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/django/db/models/loading.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/django/db/models/loading.py')
-rw-r--r--lib/python2.7/site-packages/django/db/models/loading.py327
1 files changed, 0 insertions, 327 deletions
diff --git a/lib/python2.7/site-packages/django/db/models/loading.py b/lib/python2.7/site-packages/django/db/models/loading.py
deleted file mode 100644
index bb87728..0000000
--- a/lib/python2.7/site-packages/django/db/models/loading.py
+++ /dev/null
@@ -1,327 +0,0 @@
-"Utilities for loading models and the modules that contain them."
-
-from django.conf import settings
-from django.core.exceptions import ImproperlyConfigured
-from django.utils.datastructures import SortedDict
-from django.utils.importlib import import_module
-from django.utils.module_loading import module_has_submodule
-from django.utils._os import upath
-from django.utils import six
-
-import imp
-import sys
-import os
-
-__all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
- 'load_app', 'app_cache_ready')
-
-class UnavailableApp(Exception):
- pass
-
-class AppCache(object):
- """
- A cache that stores installed applications and their models. Used to
- provide reverse-relations and for app introspection (e.g. admin).
- """
- # Use the Borg pattern to share state between all instances. Details at
- # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531.
- __shared_state = dict(
- # Keys of app_store are the model modules for each application.
- app_store=SortedDict(),
-
- # Mapping of installed app_labels to model modules for that app.
- app_labels={},
-
- # Mapping of app_labels to a dictionary of model names to model code.
- # May contain apps that are not installed.
- app_models=SortedDict(),
-
- # Mapping of app_labels to errors raised when trying to import the app.
- app_errors={},
-
- # -- Everything below here is only used when populating the cache --
- loaded=False,
- handled=set(),
- postponed=[],
- nesting_level=0,
- _get_models_cache={},
- available_apps=None,
- )
-
- def __init__(self):
- self.__dict__ = self.__shared_state
-
- def _populate(self):
- """
- Fill in all the cache information. This method is threadsafe, in the
- sense that every caller will see the same state upon return, and if the
- cache is already initialised, it does no work.
- """
- if self.loaded:
- return
- # Note that we want to use the import lock here - the app loading is
- # in many cases initiated implicitly by importing, and thus it is
- # possible to end up in deadlock when one thread initiates loading
- # without holding the importer lock and another thread then tries to
- # import something which also launches the app loading. For details of
- # this situation see #18251.
- imp.acquire_lock()
- try:
- if self.loaded:
- return
- for app_name in settings.INSTALLED_APPS:
- if app_name in self.handled:
- continue
- self.load_app(app_name, True)
- if not self.nesting_level:
- for app_name in self.postponed:
- self.load_app(app_name)
- self.loaded = True
- finally:
- imp.release_lock()
-
- def _label_for(self, app_mod):
- """
- Return app_label for given models module.
-
- """
- return app_mod.__name__.split('.')[-2]
-
- def load_app(self, app_name, can_postpone=False):
- """
- Loads the app with the provided fully qualified name, and returns the
- model module.
- """
- self.handled.add(app_name)
- self.nesting_level += 1
- app_module = import_module(app_name)
- try:
- models = import_module('%s.models' % app_name)
- except ImportError:
- self.nesting_level -= 1
- # If the app doesn't have a models module, we can just ignore the
- # ImportError and return no models for it.
- if not module_has_submodule(app_module, 'models'):
- return None
- # But if the app does have a models module, we need to figure out
- # whether to suppress or propagate the error. If can_postpone is
- # True then it may be that the package is still being imported by
- # Python and the models module isn't available yet. So we add the
- # app to the postponed list and we'll try it again after all the
- # recursion has finished (in populate). If can_postpone is False
- # then it's time to raise the ImportError.
- else:
- if can_postpone:
- self.postponed.append(app_name)
- return None
- else:
- raise
-
- self.nesting_level -= 1
- if models not in self.app_store:
- self.app_store[models] = len(self.app_store)
- self.app_labels[self._label_for(models)] = models
- return models
-
- def app_cache_ready(self):
- """
- Returns true if the model cache is fully populated.
-
- Useful for code that wants to cache the results of get_models() for
- themselves once it is safe to do so.
- """
- return self.loaded
-
- def get_apps(self):
- """
- Returns a list of all installed modules that contain models.
- """
- self._populate()
-
- apps = self.app_store.items()
- if self.available_apps is not None:
- apps = [elt for elt in apps
- if self._label_for(elt[0]) in self.available_apps]
-
- # Ensure the returned list is always in the same order (with new apps
- # added at the end). This avoids unstable ordering on the admin app
- # list page, for example.
- apps = sorted(apps, key=lambda elt: elt[1])
-
- return [elt[0] for elt in apps]
-
- def get_app_paths(self):
- """
- Returns a list of paths to all installed apps.
-
- Useful for discovering files at conventional locations inside apps
- (static files, templates, etc.)
- """
- self._populate()
-
- app_paths = []
- for app in self.get_apps():
- if hasattr(app, '__path__'): # models/__init__.py package
- app_paths.extend([upath(path) for path in app.__path__])
- else: # models.py module
- app_paths.append(upath(app.__file__))
- return app_paths
-
- def get_app(self, app_label, emptyOK=False):
- """
- Returns the module containing the models for the given app_label.
-
- Returns None if the app has no models in it and emptyOK is True.
-
- Raises UnavailableApp when set_available_apps() in in effect and
- doesn't include app_label.
- """
- self._populate()
- imp.acquire_lock()
- try:
- for app_name in settings.INSTALLED_APPS:
- if app_label == app_name.split('.')[-1]:
- mod = self.load_app(app_name, False)
- if mod is None and not emptyOK:
- raise ImproperlyConfigured("App with label %s is missing a models.py module." % app_label)
- if self.available_apps is not None and app_label not in self.available_apps:
- raise UnavailableApp("App with label %s isn't available." % app_label)
- return mod
- raise ImproperlyConfigured("App with label %s could not be found" % app_label)
- finally:
- imp.release_lock()
-
- def get_app_errors(self):
- "Returns the map of known problems with the INSTALLED_APPS."
- self._populate()
- return self.app_errors
-
- def get_models(self, app_mod=None,
- include_auto_created=False, include_deferred=False,
- only_installed=True, include_swapped=False):
- """
- Given a module containing models, returns a list of the models.
- Otherwise returns a list of all installed models.
-
- By default, auto-created models (i.e., m2m models without an
- explicit intermediate table) are not included. However, if you
- specify include_auto_created=True, they will be.
-
- By default, models created to satisfy deferred attribute
- queries are *not* included in the list of models. However, if
- you specify include_deferred, they will be.
-
- By default, models that aren't part of installed apps will *not*
- be included in the list of models. However, if you specify
- only_installed=False, they will be.
-
- By default, models that have been swapped out will *not* be
- included in the list of models. However, if you specify
- include_swapped, they will be.
- """
- cache_key = (app_mod, include_auto_created, include_deferred, only_installed, include_swapped)
- model_list = None
- try:
- model_list = self._get_models_cache[cache_key]
- if self.available_apps is not None and only_installed:
- model_list = [m for m in model_list
- if m._meta.app_label in self.available_apps]
- return model_list
- except KeyError:
- pass
- self._populate()
- if app_mod:
- if app_mod in self.app_store:
- app_list = [self.app_models.get(self._label_for(app_mod),
- SortedDict())]
- else:
- app_list = []
- else:
- if only_installed:
- app_list = [self.app_models.get(app_label, SortedDict())
- for app_label in six.iterkeys(self.app_labels)]
- else:
- app_list = six.itervalues(self.app_models)
- model_list = []
- for app in app_list:
- model_list.extend(
- model for model in app.values()
- if ((not model._deferred or include_deferred) and
- (not model._meta.auto_created or include_auto_created) and
- (not model._meta.swapped or include_swapped))
- )
- self._get_models_cache[cache_key] = model_list
- if self.available_apps is not None and only_installed:
- model_list = [m for m in model_list
- if m._meta.app_label in self.available_apps]
- return model_list
-
- def get_model(self, app_label, model_name,
- seed_cache=True, only_installed=True):
- """
- Returns the model matching the given app_label and case-insensitive
- model_name.
-
- Returns None if no model is found.
-
- Raises UnavailableApp when set_available_apps() in in effect and
- doesn't include app_label.
- """
- if seed_cache:
- self._populate()
- if only_installed and app_label not in self.app_labels:
- return None
- if (self.available_apps is not None and only_installed
- and app_label not in self.available_apps):
- raise UnavailableApp("App with label %s isn't available." % app_label)
- try:
- return self.app_models[app_label][model_name.lower()]
- except KeyError:
- return None
-
- def register_models(self, app_label, *models):
- """
- Register a set of models as belonging to an app.
- """
- for model in models:
- # Store as 'name: model' pair in a dictionary
- # in the app_models dictionary
- model_name = model._meta.model_name
- model_dict = self.app_models.setdefault(app_label, SortedDict())
- if model_name in model_dict:
- # The same model may be imported via different paths (e.g.
- # appname.models and project.appname.models). We use the source
- # filename as a means to detect identity.
- fname1 = os.path.abspath(upath(sys.modules[model.__module__].__file__))
- fname2 = os.path.abspath(upath(sys.modules[model_dict[model_name].__module__].__file__))
- # Since the filename extension could be .py the first time and
- # .pyc or .pyo the second time, ignore the extension when
- # comparing.
- if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]:
- continue
- model_dict[model_name] = model
- self._get_models_cache.clear()
-
- def set_available_apps(self, available):
- if not set(available).issubset(set(settings.INSTALLED_APPS)):
- extra = set(available) - set(settings.INSTALLED_APPS)
- raise ValueError("Available apps isn't a subset of installed "
- "apps, extra apps: " + ", ".join(extra))
- self.available_apps = set(app.rsplit('.', 1)[-1] for app in available)
-
- def unset_available_apps(self):
- self.available_apps = None
-
-cache = AppCache()
-
-# These methods were always module level, so are kept that way for backwards
-# compatibility.
-get_apps = cache.get_apps
-get_app_paths = cache.get_app_paths
-get_app = cache.get_app
-get_app_errors = cache.get_app_errors
-get_models = cache.get_models
-get_model = cache.get_model
-register_models = cache.register_models
-load_app = cache.load_app
-app_cache_ready = cache.app_cache_ready