From 2fef9e5375b0267734392080858d9fced15ee2f9 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sun, 22 Dec 2013 11:35:17 +0100 Subject: Moved apps back in the toplevel django namespace. Reverted 4a56a93cc458e9ab4dcab95d9f5067d4975dd1a2. --- django/apps/__init__.py | 1 + django/apps/base.py | 106 +++++ django/apps/cache.py | 498 +++++++++++++++++++++ django/contrib/admin/sites.py | 2 +- django/contrib/admin/templatetags/admin_static.py | 2 +- django/contrib/admin/validation.py | 2 +- django/contrib/admindocs/views.py | 2 +- django/contrib/auth/__init__.py | 2 +- django/contrib/auth/management/__init__.py | 2 +- django/contrib/auth/tests/test_management.py | 2 +- django/contrib/comments/__init__.py | 2 +- django/contrib/comments/views/comments.py | 2 +- django/contrib/contenttypes/management.py | 2 +- django/contrib/contenttypes/models.py | 2 +- django/contrib/contenttypes/tests.py | 2 +- django/contrib/gis/sitemaps/kml.py | 2 +- django/contrib/gis/sitemaps/views.py | 2 +- django/contrib/gis/tests/geoapp/test_feeds.py | 2 +- django/contrib/gis/tests/geoapp/test_sitemaps.py | 2 +- django/contrib/messages/tests/base.py | 2 +- django/contrib/redirects/middleware.py | 2 +- django/contrib/redirects/tests.py | 2 +- django/contrib/sitemaps/tests/test_flatpages.py | 2 +- django/contrib/sitemaps/tests/test_http.py | 2 +- django/contrib/sites/tests.py | 2 +- django/contrib/staticfiles/finders.py | 2 +- django/core/apps/__init__.py | 1 - django/core/apps/base.py | 106 ----- django/core/apps/cache.py | 498 --------------------- django/core/checks/compatibility/django_1_6_0.py | 2 +- django/core/management/__init__.py | 4 +- django/core/management/base.py | 2 +- django/core/management/commands/dumpdata.py | 4 +- django/core/management/commands/flush.py | 2 +- django/core/management/commands/loaddata.py | 2 +- django/core/management/commands/makemigrations.py | 2 +- django/core/management/commands/migrate.py | 2 +- django/core/management/commands/shell.py | 2 +- .../core/management/commands/sqlsequencereset.py | 2 +- django/core/management/sql.py | 2 +- django/core/management/validation.py | 2 +- django/core/serializers/base.py | 2 +- django/core/serializers/python.py | 2 +- django/core/serializers/xml_serializer.py | 2 +- django/db/backends/__init__.py | 6 +- django/db/backends/sqlite3/schema.py | 2 +- django/db/migrations/loader.py | 2 +- django/db/migrations/questioner.py | 2 +- django/db/migrations/recorder.py | 2 +- django/db/migrations/state.py | 2 +- django/db/migrations/writer.py | 2 +- django/db/models/base.py | 4 +- django/db/models/fields/__init__.py | 2 +- django/db/models/loading.py | 2 +- django/db/models/options.py | 2 +- django/db/models/signals.py | 2 +- django/db/utils.py | 2 +- django/template/base.py | 2 +- django/template/loaders/app_directories.py | 2 +- django/template/loaders/eggs.py | 2 +- django/test/client.py | 2 +- django/test/simple.py | 2 +- django/test/testcases.py | 2 +- django/utils/autoreload.py | 2 +- django/utils/module_loading.py | 2 +- django/utils/translation/trans_real.py | 2 +- django/views/i18n.py | 2 +- tests/admin_docs/tests.py | 2 +- tests/app_cache/models.py | 2 +- tests/app_cache/tests.py | 4 +- tests/app_loading/tests.py | 4 +- tests/bash_completion/tests.py | 2 +- tests/commands_sql/tests.py | 2 +- tests/comment_tests/tests/test_app_api.py | 2 +- tests/contenttypes_tests/tests.py | 2 +- tests/defer_regress/tests.py | 2 +- tests/i18n/tests.py | 2 +- tests/invalid_models_tests/tests.py | 2 +- tests/managers_regress/tests.py | 2 +- tests/migrations/models.py | 2 +- tests/migrations/test_commands.py | 2 +- tests/migrations/test_state.py | 2 +- tests/migrations/test_writer.py | 2 +- tests/no_models/tests.py | 2 +- tests/proxy_model_inheritance/tests.py | 2 +- tests/proxy_models/tests.py | 2 +- tests/runtests.py | 4 +- tests/schema/models.py | 2 +- tests/swappable_models/tests.py | 2 +- tests/tablespaces/tests.py | 2 +- tests/template_tests/test_loaders.py | 2 +- tests/template_tests/tests.py | 2 +- tests/test_runner/tests.py | 4 +- tests/test_suite_override/tests.py | 2 +- tests/utils_tests/test_autoreload.py | 2 +- tests/utils_tests/test_module_loading.py | 2 +- tests/validation/test_unique.py | 2 +- tests/view_tests/tests/test_i18n.py | 2 +- 98 files changed, 706 insertions(+), 706 deletions(-) create mode 100644 django/apps/__init__.py create mode 100644 django/apps/base.py create mode 100644 django/apps/cache.py delete mode 100644 django/core/apps/__init__.py delete mode 100644 django/core/apps/base.py delete mode 100644 django/core/apps/cache.py diff --git a/django/apps/__init__.py b/django/apps/__init__.py new file mode 100644 index 0000000000..0384b1257d --- /dev/null +++ b/django/apps/__init__.py @@ -0,0 +1 @@ +from .cache import app_cache, UnavailableApp # NOQA diff --git a/django/apps/base.py b/django/apps/base.py new file mode 100644 index 0000000000..706ed54ef6 --- /dev/null +++ b/django/apps/base.py @@ -0,0 +1,106 @@ +from importlib import import_module + +from django.core.exceptions import ImproperlyConfigured +from django.utils.module_loading import import_by_path, module_has_submodule +from django.utils._os import upath + + +MODELS_MODULE_NAME = 'models' + + +class AppConfig(object): + """ + Class representing a Django application and its configuration. + """ + + def __init__(self, app_name): + # Full Python path to the application eg. 'django.contrib.admin'. + self.name = app_name + + # Root module for the application eg. . + self.app_module = import_module(app_name) + + # The following attributes could be defined at the class level in a + # subclass, hence the test-and-set pattern. + + # Last component of the Python path to the application eg. 'admin'. + # This value must be unique across a Django project. + if not hasattr(self, 'label'): + self.label = app_name.rpartition(".")[2] + + # Human-readable name for the application eg. "Admin". + if not hasattr(self, 'verbose_name'): + self.verbose_name = self.label.title() + + # Filesystem path to the application directory eg. + # u'/usr/lib/python2.7/dist-packages/django/contrib/admin'. May be + # None if the application isn't a bona fide package eg. if it's an + # egg. Otherwise it's a unicode on Python 2 and a str on Python 3. + if not hasattr(self, 'path'): + try: + self.path = upath(self.app_module.__path__[0]) + except AttributeError: + self.path = None + + # Module containing models eg. . Set by import_models(). + # None if the application doesn't have a models module. + self.models_module = None + + # Mapping of lower case model names to model classes. Initally set to + # None to prevent accidental access before import_models() runs. + self.models = None + + def __repr__(self): + return '' % self.label + + @classmethod + def create(cls, entry): + """ + Factory that creates an app config from an entry in INSTALLED_APPS. + """ + try: + # If import_module succeeds, entry is a path to an app module. + # Otherwise, entry is a path to an app config class or an error. + import_module(entry) + + except ImportError: + # Raise the original exception when entry cannot be a path to an + # app config class. Since module names are allowable here, the + # standard exception message from import_by_path is unsuitable. + if '.' not in entry: + raise + + cls = import_by_path(entry) + + # Check for obvious errors. (This check prevents duck typing, but + # it could be removed if it became a problem in practice.) + if not issubclass(cls, AppConfig): + raise ImproperlyConfigured( + "%r isn't a subclass of AppConfig." % entry) + + # Obtain app name here rather than in AppClass.__init__ to keep + # all error checking for entries in INSTALLED_APPS in one place. + try: + app_name = cls.name + except AttributeError: + raise ImproperlyConfigured( + "%r must supply a name attribute." % entry) + + # Entry is a path to an app config class. + return cls(app_name) + + else: + # Entry is a path to an app module. + return cls(entry) + + def import_models(self, all_models): + # Dictionary of models for this app, stored in the 'all_models' + # attribute of the AppCache this AppConfig is attached to. Injected as + # a parameter because it may get populated before this method has run. + self.models = all_models + + if module_has_submodule(self.app_module, MODELS_MODULE_NAME): + models_module_name = '%s.%s' % (self.name, MODELS_MODULE_NAME) + self.models_module = import_module(models_module_name) diff --git a/django/apps/cache.py b/django/apps/cache.py new file mode 100644 index 0000000000..056aa9a60b --- /dev/null +++ b/django/apps/cache.py @@ -0,0 +1,498 @@ +"Utilities for loading models and the modules that contain them." + +from collections import defaultdict, OrderedDict +from contextlib import contextmanager +import os +import sys +import warnings + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.utils.module_loading import import_lock +from django.utils._os import upath + +from .base import AppConfig + + +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. + """ + + def __init__(self, master=False): + # Only one master of the app-cache may exist at a given time, and it + # shall be the app_cache variable defined at the end of this module. + if master and hasattr(sys.modules[__name__], 'app_cache'): + raise RuntimeError("You may create only one master app cache.") + + # When master is set to False, the app cache isn't populated from + # INSTALLED_APPS and ignores the only_installed arguments to + # get_model[s]. + self.master = master + + # Mapping of app labels => model names => model classes. Used to + # register models before the app cache is populated and also for + # applications that aren't installed. + self.all_models = defaultdict(OrderedDict) + + # Mapping of labels to AppConfig instances for installed apps. + self.app_configs = OrderedDict() + + # Set of app names. Allows restricting the set of installed apps. + # Used by TransactionTestCase.available_apps for performance reasons. + self.available_apps = None + + # Internal flags used when populating the master cache. + self._apps_loaded = not self.master + self._models_loaded = not self.master + + # Pending lookups for lazy relations. + self._pending_lookups = {} + + # Cache for get_models. + self._get_models_cache = {} + + def populate_apps(self): + """ + Populate app-related information. + + This method imports each application module. + + It is thread safe and idempotent, but not reentrant. + """ + if self._apps_loaded: + return + # Since populate_apps() may be a side effect of imports, and since + # it will itself import modules, an ABBA deadlock between threads + # would be possible if we didn't take the import lock. See #18251. + with import_lock(): + if self._apps_loaded: + return + + # app_config should be pristine, otherwise the code below won't + # guarantee that the order matches the order in INSTALLED_APPS. + if self.app_configs: + raise RuntimeError("populate_apps() isn't reentrant") + + # Application modules aren't expected to import anything, and + # especially not other application modules, even indirectly. + # Therefore we simply import them sequentially. + for app_name in settings.INSTALLED_APPS: + app_config = AppConfig.create(app_name) + self.app_configs[app_config.label] = app_config + + self._apps_loaded = True + + def populate_models(self): + """ + Populate model-related information. + + This method imports each models module. + + It is thread safe, idempotent and reentrant. + """ + if self._models_loaded: + return + # Since populate_models() may be a side effect of imports, and since + # it will itself import modules, an ABBA deadlock between threads + # would be possible if we didn't take the import lock. See #18251. + with import_lock(): + if self._models_loaded: + return + + self.populate_apps() + + # Models modules are likely to import other models modules, for + # example to reference related objects. As a consequence: + # - we deal with import loops by postponing affected modules. + # - we provide reentrancy by making import_models() idempotent. + + outermost = not hasattr(self, '_postponed') + if outermost: + self._postponed = [] + + for app_config in self.app_configs.values(): + + try: + all_models = self.all_models[app_config.label] + app_config.import_models(all_models) + except ImportError: + self._postponed.append(app_config) + + if outermost: + for app_config in self._postponed: + all_models = self.all_models[app_config.label] + app_config.import_models(all_models) + + del self._postponed + + self._models_loaded = True + + 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._models_loaded # implies self._apps_loaded. + + def get_app_configs(self, only_with_models_module=False): + """ + Imports applications and returns an iterable of app configs. + + If only_with_models_module in True (non-default), imports models and + considers only applications containing a models module. + """ + if only_with_models_module: + self.populate_models() + else: + self.populate_apps() + + for app_config in self.app_configs.values(): + if only_with_models_module and app_config.models_module is None: + continue + if self.available_apps is not None and app_config.name not in self.available_apps: + continue + yield app_config + + def get_app_config(self, app_label, only_with_models_module=False): + """ + Imports applications and returns an app config for the given label. + + Raises LookupError if no application exists with this label. + + Raises UnavailableApp when set_available_apps() disables the + application with this label. + + If only_with_models_module in True (non-default), imports models and + considers only applications containing a models module. + """ + if only_with_models_module: + self.populate_models() + else: + self.populate_apps() + + app_config = self.app_configs.get(app_label) + if app_config is None: + raise LookupError("No installed app with label %r." % app_label) + if only_with_models_module and app_config.models_module is None: + raise LookupError("App with label %r doesn't have a models module." % app_label) + if self.available_apps is not None and app_config.name not in self.available_apps: + raise UnavailableApp("App with label %r isn't available." % app_label) + return app_config + + 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. If you're using a non-default + AppCache, this argument does nothing - all models will be included. + + 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. + """ + if not self.master: + only_installed = False + 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 self.app_configs[m._meta.app_label].name in self.available_apps + ] + return model_list + except KeyError: + pass + self.populate_models() + if app_mod: + app_label = app_mod.__name__.split('.')[-2] + if only_installed: + try: + model_dicts = [self.app_configs[app_label].models] + except KeyError: + model_dicts = [] + else: + model_dicts = [self.all_models[app_label]] + else: + if only_installed: + model_dicts = [app_config.models for app_config in self.app_configs.values()] + else: + model_dicts = self.all_models.values() + model_list = [] + for model_dict in model_dicts: + model_list.extend( + model for model in model_dict.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 self.app_configs[m._meta.app_label].name in self.available_apps + ] + return model_list + + def get_model(self, app_label, model_name, 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 not self.master: + only_installed = False + self.populate_models() + if only_installed: + app_config = self.app_configs.get(app_label) + if app_config is None: + return None + if (self.available_apps is not None + and app_config.name not in self.available_apps): + raise UnavailableApp("App with label %s isn't available." % app_label) + return self.all_models[app_label].get(model_name.lower()) + + def register_model(self, app_label, model): + # Since this method is called when models are imported, it cannot + # perform imports because of the risk of import loops. It mustn't + # call get_app_config(). + model_name = model._meta.model_name + models = self.all_models[app_label] + if model_name in models: + # 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[models[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]: + return + models[model_name] = model + self._get_models_cache.clear() + + def has_app(self, app_name): + """ + Returns the application config if one is registered and None otherwise. + + It's safe to call this method at import time, even while the app cache + is being populated. It returns None for apps that aren't loaded yet. + """ + app_config = self.app_configs.get(app_name.rpartition(".")[2]) + if app_config is not None and app_config.name != app_name: + app_config = None + return app_config + + def has_model(self, app_label, model_name): + """ + Returns the model class if one is registered and None otherwise. + + It's safe to call this method at import time, even while the app cache + is being populated. It returns None for models that aren't loaded yet. + """ + return self.all_models[app_label].get(model_name.lower()) + + def set_available_apps(self, available): + """ + Restricts the set of installed apps used by get_app_config[s]. + + available must be an iterable of application names. + + Primarily used for performance optimization in TransactionTestCase. + """ + if self.available_apps is not None: + raise RuntimeError("set_available_apps() may be called only once " + "in a row; make sure it's paired with unset_available_apps()") + available = set(available) + installed = set(app_config.name for app_config in self.get_app_configs()) + if not available.issubset(installed): + raise ValueError("Available apps isn't a subset of installed " + "apps, extra apps: %s" % ", ".join(available - installed)) + self.available_apps = available + + def unset_available_apps(self): + """ + Cancels a previous call to set_available_apps(). + """ + self.available_apps = None + + ### DANGEROUS METHODS ### (only used to preserve existing tests) + + def _begin_with_app(self, app_name): + # Returns an opaque value that can be passed to _end_with_app(). + app_config = AppConfig.create(app_name) + if app_config.label in self.app_configs: + return None + else: + app_config.import_models(self.all_models[app_config.label]) + self.app_configs[app_config.label] = app_config + if self.available_apps is not None: + self.available_apps.add(app_config.name) + return app_config + + def _end_with_app(self, app_config): + if app_config is not None: + del self.app_configs[app_config.label] + if self.available_apps is not None: + self.available_apps.discard(app_config.name) + + @contextmanager + def _with_app(self, app_name): + app_config = self._begin_with_app(app_name) + try: + yield + finally: + self._end_with_app(app_config) + + def _begin_without_app(self, app_name): + # Returns an opaque value that can be passed to _end_without_app(). + return self.app_configs.pop(app_name.rpartition(".")[2], None) + + def _end_without_app(self, app_config): + if app_config is not None: + self.app_configs[app_config.label] = app_config + + @contextmanager + def _without_app(self, app_name): + app_config = self._begin_without_app(app_name) + try: + yield + finally: + self._end_without_app(app_config) + + def _begin_empty(self): + app_configs, self.app_configs = self.app_configs, OrderedDict() + return app_configs + + def _end_empty(self, app_configs): + self.app_configs = app_configs + + @contextmanager + def _empty(self): + app_configs = self._begin_empty() + try: + yield + finally: + self._end_empty(app_configs) + + ### DEPRECATED METHODS GO BELOW THIS LINE ### + + def load_app(self, app_name): + """ + Loads the app with the provided fully qualified name, and returns the + model module. + """ + warnings.warn( + "load_app(app_name) is deprecated.", + PendingDeprecationWarning, stacklevel=2) + app_config = AppConfig.create(app_name) + app_config.import_models(self.all_models[app_config.label]) + self.app_configs[app_config.label] = app_config + return app_config.models_module + + def get_app(self, app_label): + """ + Returns the module containing the models for the given app_label. + + Raises UnavailableApp when set_available_apps() in in effect and + doesn't include app_label. + """ + warnings.warn( + "get_app_config(app_label).models_module supersedes get_app(app_label).", + PendingDeprecationWarning, stacklevel=2) + try: + return self.get_app_config( + app_label, only_with_models_module=True).models_module + except LookupError as exc: + # Change the exception type for backwards compatibility. + raise ImproperlyConfigured(*exc.args) + + def get_apps(self): + """ + Returns a list of all installed modules that contain models. + """ + warnings.warn( + "[a.models_module for a in get_app_configs()] supersedes get_apps().", + PendingDeprecationWarning, stacklevel=2) + app_configs = self.get_app_configs(only_with_models_module=True) + return [app_config.models_module for app_config in app_configs] + + def _get_app_package(self, app): + return '.'.join(app.__name__.split('.')[:-1]) + + def get_app_package(self, app_label): + warnings.warn( + "get_app_config(label).name supersedes get_app_package(label).", + PendingDeprecationWarning, stacklevel=2) + return self._get_app_package(self.get_app(app_label)) + + def _get_app_path(self, app): + if hasattr(app, '__path__'): # models/__init__.py package + app_path = app.__path__[0] + else: # models.py module + app_path = app.__file__ + return os.path.dirname(upath(app_path)) + + def get_app_path(self, app_label): + warnings.warn( + "get_app_config(label).path supersedes get_app_path(label).", + PendingDeprecationWarning, stacklevel=2) + return self._get_app_path(self.get_app(app_label)) + + 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.) + """ + warnings.warn( + "[a.path for a in get_app_configs()] supersedes get_app_paths().", + PendingDeprecationWarning, stacklevel=2) + + self.populate_models() + + app_paths = [] + for app in self.get_apps(): + app_paths.append(self._get_app_path(app)) + return app_paths + + def register_models(self, app_label, *models): + """ + Register a set of models as belonging to an app. + """ + warnings.warn( + "register_models(app_label, *models) is deprecated.", + PendingDeprecationWarning, stacklevel=2) + for model in models: + self.register_model(app_label, model) + + +app_cache = AppCache(master=True) diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index a4caa863eb..d72666a257 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -6,7 +6,7 @@ from django.contrib.auth import logout as auth_logout, REDIRECT_FIELD_NAME from django.contrib.contenttypes import views as contenttype_views from django.views.decorators.csrf import csrf_protect from django.db.models.base import ModelBase -from django.core.apps import app_cache +from django.apps import app_cache from django.core.exceptions import ImproperlyConfigured, PermissionDenied from django.core.urlresolvers import reverse, NoReverseMatch from django.template.response import TemplateResponse diff --git a/django/contrib/admin/templatetags/admin_static.py b/django/contrib/admin/templatetags/admin_static.py index 75b077057e..7c7a5e5654 100644 --- a/django/contrib/admin/templatetags/admin_static.py +++ b/django/contrib/admin/templatetags/admin_static.py @@ -1,4 +1,4 @@ -from django.core.apps import app_cache +from django.apps import app_cache from django.template import Library register = Library() diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py index ee945f73e5..18e3ad48f8 100644 --- a/django/contrib/admin/validation.py +++ b/django/contrib/admin/validation.py @@ -1,4 +1,4 @@ -from django.core.apps import app_cache +from django.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django.db import models from django.db.models.fields import FieldDoesNotExist diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py index 9e6dd85595..973c81ddaf 100644 --- a/django/contrib/admindocs/views.py +++ b/django/contrib/admindocs/views.py @@ -5,10 +5,10 @@ import re import warnings from django import template +from django.apps import app_cache from django.conf import settings from django.contrib import admin from django.contrib.admin.views.decorators import staff_member_required -from django.core.apps import app_cache from django.db import models from django.core.exceptions import ViewDoesNotExist from django.http import Http404 diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index d5fc14dd2a..3c5a40c184 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -123,7 +123,7 @@ def get_user_model(): """ Returns the User model that is active in this project. """ - from django.core.apps import app_cache + from django.apps import app_cache try: app_label, model_name = settings.AUTH_USER_MODEL.split('.') diff --git a/django/contrib/auth/management/__init__.py b/django/contrib/auth/management/__init__.py index ec963becc4..5f24bf069e 100644 --- a/django/contrib/auth/management/__init__.py +++ b/django/contrib/auth/management/__init__.py @@ -6,9 +6,9 @@ from __future__ import unicode_literals import getpass import unicodedata +from django.apps import app_cache, UnavailableApp from django.contrib.auth import (models as auth_app, get_permission_codename, get_user_model) -from django.core.apps import app_cache, UnavailableApp from django.core import exceptions from django.core.management.base import CommandError from django.db import DEFAULT_DB_ALIAS, router diff --git a/django/contrib/auth/tests/test_management.py b/django/contrib/auth/tests/test_management.py index d9de5a2ad0..c005e74442 100644 --- a/django/contrib/auth/tests/test_management.py +++ b/django/contrib/auth/tests/test_management.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals from datetime import date +from django.apps import app_cache from django.contrib.auth import models, management from django.contrib.auth.management import create_permissions from django.contrib.auth.management.commands import changepassword @@ -8,7 +9,6 @@ from django.contrib.auth.models import User from django.contrib.auth.tests.custom_user import CustomUser from django.contrib.auth.tests.utils import skipIfCustomUser from django.contrib.contenttypes.models import ContentType -from django.core.apps import app_cache from django.core import exceptions from django.core.management import call_command from django.core.management.base import CommandError diff --git a/django/contrib/comments/__init__.py b/django/contrib/comments/__init__.py index 8d4b922966..f265875c36 100644 --- a/django/contrib/comments/__init__.py +++ b/django/contrib/comments/__init__.py @@ -1,8 +1,8 @@ from importlib import import_module import warnings +from django.apps import app_cache from django.conf import settings from django.core import urlresolvers -from django.core.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django.contrib.comments.models import Comment from django.contrib.comments.forms import CommentForm diff --git a/django/contrib/comments/views/comments.py b/django/contrib/comments/views/comments.py index 294c7c8e42..5d7c543adb 100644 --- a/django/contrib/comments/views/comments.py +++ b/django/contrib/comments/views/comments.py @@ -1,9 +1,9 @@ from django import http +from django.apps import app_cache from django.conf import settings from django.contrib import comments from django.contrib.comments import signals from django.contrib.comments.views.utils import next_redirect, confirmation_view -from django.core.apps import app_cache from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models from django.shortcuts import render_to_response diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py index 7ff08b70f8..35a8a7fdc8 100644 --- a/django/contrib/contenttypes/management.py +++ b/django/contrib/contenttypes/management.py @@ -1,5 +1,5 @@ +from django.apps import app_cache, UnavailableApp from django.contrib.contenttypes.models import ContentType -from django.core.apps import app_cache, UnavailableApp from django.db import DEFAULT_DB_ALIAS, router from django.db.models import signals from django.utils.encoding import smart_text diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py index 98eae0219c..90dea5b811 100644 --- a/django/contrib/contenttypes/models.py +++ b/django/contrib/contenttypes/models.py @@ -1,4 +1,4 @@ -from django.core.apps import app_cache +from django.apps import app_cache from django.db import models from django.utils.translation import ugettext_lazy as _ from django.utils.encoding import smart_text, force_text diff --git a/django/contrib/contenttypes/tests.py b/django/contrib/contenttypes/tests.py index b194755b80..302cdbb5cf 100644 --- a/django/contrib/contenttypes/tests.py +++ b/django/contrib/contenttypes/tests.py @@ -1,9 +1,9 @@ from __future__ import unicode_literals +from django.apps import app_cache from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.views import shortcut from django.contrib.sites.models import get_current_site -from django.core.apps import app_cache from django.db import models from django.http import HttpRequest, Http404 from django.test import TestCase diff --git a/django/contrib/gis/sitemaps/kml.py b/django/contrib/gis/sitemaps/kml.py index aa9ae69f5d..1e4fc82550 100644 --- a/django/contrib/gis/sitemaps/kml.py +++ b/django/contrib/gis/sitemaps/kml.py @@ -1,4 +1,4 @@ -from django.core.apps import app_cache +from django.apps import app_cache from django.core import urlresolvers from django.contrib.sitemaps import Sitemap from django.contrib.gis.db.models.fields import GeometryField diff --git a/django/contrib/gis/sitemaps/views.py b/django/contrib/gis/sitemaps/views.py index e55a371672..e68523981e 100644 --- a/django/contrib/gis/sitemaps/views.py +++ b/django/contrib/gis/sitemaps/views.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import warnings -from django.core.apps import app_cache +from django.apps import app_cache from django.http import HttpResponse, Http404 from django.template import loader from django.contrib.sites.models import get_current_site diff --git a/django/contrib/gis/tests/geoapp/test_feeds.py b/django/contrib/gis/tests/geoapp/test_feeds.py index 6f0d901a62..638944db63 100644 --- a/django/contrib/gis/tests/geoapp/test_feeds.py +++ b/django/contrib/gis/tests/geoapp/test_feeds.py @@ -3,11 +3,11 @@ from __future__ import unicode_literals from unittest import skipUnless from xml.dom import minidom +from django.apps import app_cache from django.conf import settings from django.contrib.sites.models import Site from django.contrib.gis.geos import HAS_GEOS from django.contrib.gis.tests.utils import HAS_SPATIAL_DB -from django.core.apps import app_cache from django.test import TestCase if HAS_GEOS: diff --git a/django/contrib/gis/tests/geoapp/test_sitemaps.py b/django/contrib/gis/tests/geoapp/test_sitemaps.py index 035d97af34..909a543bb6 100644 --- a/django/contrib/gis/tests/geoapp/test_sitemaps.py +++ b/django/contrib/gis/tests/geoapp/test_sitemaps.py @@ -6,11 +6,11 @@ from xml.dom import minidom import os import zipfile +from django.apps import app_cache from django.conf import settings from django.contrib.gis.geos import HAS_GEOS from django.contrib.gis.tests.utils import HAS_SPATIAL_DB from django.contrib.sites.models import Site -from django.core.apps import app_cache from django.test import TestCase from django.test.utils import IgnoreDeprecationWarningsMixin from django.utils._os import upath diff --git a/django/contrib/messages/tests/base.py b/django/contrib/messages/tests/base.py index 8d7906ba52..e03d229be3 100644 --- a/django/contrib/messages/tests/base.py +++ b/django/contrib/messages/tests/base.py @@ -1,13 +1,13 @@ from unittest import skipUnless from django import http +from django.apps import app_cache from django.conf import settings, global_settings from django.contrib.messages import constants, utils, get_level, set_level from django.contrib.messages.api import MessageFailure from django.contrib.messages.constants import DEFAULT_LEVELS from django.contrib.messages.storage import default_storage, base from django.contrib.messages.storage.base import Message -from django.core.apps import app_cache from django.core.urlresolvers import reverse from django.test.utils import override_settings from django.utils.translation import ugettext_lazy diff --git a/django/contrib/redirects/middleware.py b/django/contrib/redirects/middleware.py index e8aa06ebb1..c5b672659e 100644 --- a/django/contrib/redirects/middleware.py +++ b/django/contrib/redirects/middleware.py @@ -1,9 +1,9 @@ from __future__ import unicode_literals +from django.apps import app_cache from django.conf import settings from django.contrib.redirects.models import Redirect from django.contrib.sites.models import get_current_site -from django.core.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django import http diff --git a/django/contrib/redirects/tests.py b/django/contrib/redirects/tests.py index 8566a34c68..0784a6a6f3 100644 --- a/django/contrib/redirects/tests.py +++ b/django/contrib/redirects/tests.py @@ -1,7 +1,7 @@ from django import http +from django.apps import app_cache from django.conf import settings from django.contrib.sites.models import Site -from django.core.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django.test import TestCase from django.test.utils import override_settings diff --git a/django/contrib/sitemaps/tests/test_flatpages.py b/django/contrib/sitemaps/tests/test_flatpages.py index 33ba168a45..90172e558f 100644 --- a/django/contrib/sitemaps/tests/test_flatpages.py +++ b/django/contrib/sitemaps/tests/test_flatpages.py @@ -2,8 +2,8 @@ from __future__ import unicode_literals from unittest import skipUnless +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from .base import SitemapTestsBase diff --git a/django/contrib/sitemaps/tests/test_http.py b/django/contrib/sitemaps/tests/test_http.py index 94d9adea49..fca644538b 100644 --- a/django/contrib/sitemaps/tests/test_http.py +++ b/django/contrib/sitemaps/tests/test_http.py @@ -4,10 +4,10 @@ import os from datetime import date from unittest import skipUnless +from django.apps import app_cache from django.conf import settings from django.contrib.sitemaps import Sitemap, GenericSitemap from django.contrib.sites.models import Site -from django.core.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django.test.utils import override_settings from django.utils.formats import localize diff --git a/django/contrib/sites/tests.py b/django/contrib/sites/tests.py index 8d76fd0d02..79bcae9aa6 100644 --- a/django/contrib/sites/tests.py +++ b/django/contrib/sites/tests.py @@ -1,8 +1,8 @@ from __future__ import unicode_literals +from django.apps import app_cache from django.conf import settings from django.contrib.sites.models import Site, RequestSite, get_current_site -from django.core.apps import app_cache from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.http import HttpRequest from django.test import TestCase diff --git a/django/contrib/staticfiles/finders.py b/django/contrib/staticfiles/finders.py index cadc8bffa7..de907ef8ef 100644 --- a/django/contrib/staticfiles/finders.py +++ b/django/contrib/staticfiles/finders.py @@ -1,8 +1,8 @@ from collections import OrderedDict import os +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django.core.files.storage import default_storage, Storage, FileSystemStorage from django.utils.functional import empty, LazyObject diff --git a/django/core/apps/__init__.py b/django/core/apps/__init__.py deleted file mode 100644 index 0384b1257d..0000000000 --- a/django/core/apps/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .cache import app_cache, UnavailableApp # NOQA diff --git a/django/core/apps/base.py b/django/core/apps/base.py deleted file mode 100644 index 706ed54ef6..0000000000 --- a/django/core/apps/base.py +++ /dev/null @@ -1,106 +0,0 @@ -from importlib import import_module - -from django.core.exceptions import ImproperlyConfigured -from django.utils.module_loading import import_by_path, module_has_submodule -from django.utils._os import upath - - -MODELS_MODULE_NAME = 'models' - - -class AppConfig(object): - """ - Class representing a Django application and its configuration. - """ - - def __init__(self, app_name): - # Full Python path to the application eg. 'django.contrib.admin'. - self.name = app_name - - # Root module for the application eg. . - self.app_module = import_module(app_name) - - # The following attributes could be defined at the class level in a - # subclass, hence the test-and-set pattern. - - # Last component of the Python path to the application eg. 'admin'. - # This value must be unique across a Django project. - if not hasattr(self, 'label'): - self.label = app_name.rpartition(".")[2] - - # Human-readable name for the application eg. "Admin". - if not hasattr(self, 'verbose_name'): - self.verbose_name = self.label.title() - - # Filesystem path to the application directory eg. - # u'/usr/lib/python2.7/dist-packages/django/contrib/admin'. May be - # None if the application isn't a bona fide package eg. if it's an - # egg. Otherwise it's a unicode on Python 2 and a str on Python 3. - if not hasattr(self, 'path'): - try: - self.path = upath(self.app_module.__path__[0]) - except AttributeError: - self.path = None - - # Module containing models eg. . Set by import_models(). - # None if the application doesn't have a models module. - self.models_module = None - - # Mapping of lower case model names to model classes. Initally set to - # None to prevent accidental access before import_models() runs. - self.models = None - - def __repr__(self): - return '' % self.label - - @classmethod - def create(cls, entry): - """ - Factory that creates an app config from an entry in INSTALLED_APPS. - """ - try: - # If import_module succeeds, entry is a path to an app module. - # Otherwise, entry is a path to an app config class or an error. - import_module(entry) - - except ImportError: - # Raise the original exception when entry cannot be a path to an - # app config class. Since module names are allowable here, the - # standard exception message from import_by_path is unsuitable. - if '.' not in entry: - raise - - cls = import_by_path(entry) - - # Check for obvious errors. (This check prevents duck typing, but - # it could be removed if it became a problem in practice.) - if not issubclass(cls, AppConfig): - raise ImproperlyConfigured( - "%r isn't a subclass of AppConfig." % entry) - - # Obtain app name here rather than in AppClass.__init__ to keep - # all error checking for entries in INSTALLED_APPS in one place. - try: - app_name = cls.name - except AttributeError: - raise ImproperlyConfigured( - "%r must supply a name attribute." % entry) - - # Entry is a path to an app config class. - return cls(app_name) - - else: - # Entry is a path to an app module. - return cls(entry) - - def import_models(self, all_models): - # Dictionary of models for this app, stored in the 'all_models' - # attribute of the AppCache this AppConfig is attached to. Injected as - # a parameter because it may get populated before this method has run. - self.models = all_models - - if module_has_submodule(self.app_module, MODELS_MODULE_NAME): - models_module_name = '%s.%s' % (self.name, MODELS_MODULE_NAME) - self.models_module = import_module(models_module_name) diff --git a/django/core/apps/cache.py b/django/core/apps/cache.py deleted file mode 100644 index 056aa9a60b..0000000000 --- a/django/core/apps/cache.py +++ /dev/null @@ -1,498 +0,0 @@ -"Utilities for loading models and the modules that contain them." - -from collections import defaultdict, OrderedDict -from contextlib import contextmanager -import os -import sys -import warnings - -from django.conf import settings -from django.core.exceptions import ImproperlyConfigured -from django.utils.module_loading import import_lock -from django.utils._os import upath - -from .base import AppConfig - - -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. - """ - - def __init__(self, master=False): - # Only one master of the app-cache may exist at a given time, and it - # shall be the app_cache variable defined at the end of this module. - if master and hasattr(sys.modules[__name__], 'app_cache'): - raise RuntimeError("You may create only one master app cache.") - - # When master is set to False, the app cache isn't populated from - # INSTALLED_APPS and ignores the only_installed arguments to - # get_model[s]. - self.master = master - - # Mapping of app labels => model names => model classes. Used to - # register models before the app cache is populated and also for - # applications that aren't installed. - self.all_models = defaultdict(OrderedDict) - - # Mapping of labels to AppConfig instances for installed apps. - self.app_configs = OrderedDict() - - # Set of app names. Allows restricting the set of installed apps. - # Used by TransactionTestCase.available_apps for performance reasons. - self.available_apps = None - - # Internal flags used when populating the master cache. - self._apps_loaded = not self.master - self._models_loaded = not self.master - - # Pending lookups for lazy relations. - self._pending_lookups = {} - - # Cache for get_models. - self._get_models_cache = {} - - def populate_apps(self): - """ - Populate app-related information. - - This method imports each application module. - - It is thread safe and idempotent, but not reentrant. - """ - if self._apps_loaded: - return - # Since populate_apps() may be a side effect of imports, and since - # it will itself import modules, an ABBA deadlock between threads - # would be possible if we didn't take the import lock. See #18251. - with import_lock(): - if self._apps_loaded: - return - - # app_config should be pristine, otherwise the code below won't - # guarantee that the order matches the order in INSTALLED_APPS. - if self.app_configs: - raise RuntimeError("populate_apps() isn't reentrant") - - # Application modules aren't expected to import anything, and - # especially not other application modules, even indirectly. - # Therefore we simply import them sequentially. - for app_name in settings.INSTALLED_APPS: - app_config = AppConfig.create(app_name) - self.app_configs[app_config.label] = app_config - - self._apps_loaded = True - - def populate_models(self): - """ - Populate model-related information. - - This method imports each models module. - - It is thread safe, idempotent and reentrant. - """ - if self._models_loaded: - return - # Since populate_models() may be a side effect of imports, and since - # it will itself import modules, an ABBA deadlock between threads - # would be possible if we didn't take the import lock. See #18251. - with import_lock(): - if self._models_loaded: - return - - self.populate_apps() - - # Models modules are likely to import other models modules, for - # example to reference related objects. As a consequence: - # - we deal with import loops by postponing affected modules. - # - we provide reentrancy by making import_models() idempotent. - - outermost = not hasattr(self, '_postponed') - if outermost: - self._postponed = [] - - for app_config in self.app_configs.values(): - - try: - all_models = self.all_models[app_config.label] - app_config.import_models(all_models) - except ImportError: - self._postponed.append(app_config) - - if outermost: - for app_config in self._postponed: - all_models = self.all_models[app_config.label] - app_config.import_models(all_models) - - del self._postponed - - self._models_loaded = True - - 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._models_loaded # implies self._apps_loaded. - - def get_app_configs(self, only_with_models_module=False): - """ - Imports applications and returns an iterable of app configs. - - If only_with_models_module in True (non-default), imports models and - considers only applications containing a models module. - """ - if only_with_models_module: - self.populate_models() - else: - self.populate_apps() - - for app_config in self.app_configs.values(): - if only_with_models_module and app_config.models_module is None: - continue - if self.available_apps is not None and app_config.name not in self.available_apps: - continue - yield app_config - - def get_app_config(self, app_label, only_with_models_module=False): - """ - Imports applications and returns an app config for the given label. - - Raises LookupError if no application exists with this label. - - Raises UnavailableApp when set_available_apps() disables the - application with this label. - - If only_with_models_module in True (non-default), imports models and - considers only applications containing a models module. - """ - if only_with_models_module: - self.populate_models() - else: - self.populate_apps() - - app_config = self.app_configs.get(app_label) - if app_config is None: - raise LookupError("No installed app with label %r." % app_label) - if only_with_models_module and app_config.models_module is None: - raise LookupError("App with label %r doesn't have a models module." % app_label) - if self.available_apps is not None and app_config.name not in self.available_apps: - raise UnavailableApp("App with label %r isn't available." % app_label) - return app_config - - 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. If you're using a non-default - AppCache, this argument does nothing - all models will be included. - - 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. - """ - if not self.master: - only_installed = False - 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 self.app_configs[m._meta.app_label].name in self.available_apps - ] - return model_list - except KeyError: - pass - self.populate_models() - if app_mod: - app_label = app_mod.__name__.split('.')[-2] - if only_installed: - try: - model_dicts = [self.app_configs[app_label].models] - except KeyError: - model_dicts = [] - else: - model_dicts = [self.all_models[app_label]] - else: - if only_installed: - model_dicts = [app_config.models for app_config in self.app_configs.values()] - else: - model_dicts = self.all_models.values() - model_list = [] - for model_dict in model_dicts: - model_list.extend( - model for model in model_dict.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 self.app_configs[m._meta.app_label].name in self.available_apps - ] - return model_list - - def get_model(self, app_label, model_name, 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 not self.master: - only_installed = False - self.populate_models() - if only_installed: - app_config = self.app_configs.get(app_label) - if app_config is None: - return None - if (self.available_apps is not None - and app_config.name not in self.available_apps): - raise UnavailableApp("App with label %s isn't available." % app_label) - return self.all_models[app_label].get(model_name.lower()) - - def register_model(self, app_label, model): - # Since this method is called when models are imported, it cannot - # perform imports because of the risk of import loops. It mustn't - # call get_app_config(). - model_name = model._meta.model_name - models = self.all_models[app_label] - if model_name in models: - # 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[models[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]: - return - models[model_name] = model - self._get_models_cache.clear() - - def has_app(self, app_name): - """ - Returns the application config if one is registered and None otherwise. - - It's safe to call this method at import time, even while the app cache - is being populated. It returns None for apps that aren't loaded yet. - """ - app_config = self.app_configs.get(app_name.rpartition(".")[2]) - if app_config is not None and app_config.name != app_name: - app_config = None - return app_config - - def has_model(self, app_label, model_name): - """ - Returns the model class if one is registered and None otherwise. - - It's safe to call this method at import time, even while the app cache - is being populated. It returns None for models that aren't loaded yet. - """ - return self.all_models[app_label].get(model_name.lower()) - - def set_available_apps(self, available): - """ - Restricts the set of installed apps used by get_app_config[s]. - - available must be an iterable of application names. - - Primarily used for performance optimization in TransactionTestCase. - """ - if self.available_apps is not None: - raise RuntimeError("set_available_apps() may be called only once " - "in a row; make sure it's paired with unset_available_apps()") - available = set(available) - installed = set(app_config.name for app_config in self.get_app_configs()) - if not available.issubset(installed): - raise ValueError("Available apps isn't a subset of installed " - "apps, extra apps: %s" % ", ".join(available - installed)) - self.available_apps = available - - def unset_available_apps(self): - """ - Cancels a previous call to set_available_apps(). - """ - self.available_apps = None - - ### DANGEROUS METHODS ### (only used to preserve existing tests) - - def _begin_with_app(self, app_name): - # Returns an opaque value that can be passed to _end_with_app(). - app_config = AppConfig.create(app_name) - if app_config.label in self.app_configs: - return None - else: - app_config.import_models(self.all_models[app_config.label]) - self.app_configs[app_config.label] = app_config - if self.available_apps is not None: - self.available_apps.add(app_config.name) - return app_config - - def _end_with_app(self, app_config): - if app_config is not None: - del self.app_configs[app_config.label] - if self.available_apps is not None: - self.available_apps.discard(app_config.name) - - @contextmanager - def _with_app(self, app_name): - app_config = self._begin_with_app(app_name) - try: - yield - finally: - self._end_with_app(app_config) - - def _begin_without_app(self, app_name): - # Returns an opaque value that can be passed to _end_without_app(). - return self.app_configs.pop(app_name.rpartition(".")[2], None) - - def _end_without_app(self, app_config): - if app_config is not None: - self.app_configs[app_config.label] = app_config - - @contextmanager - def _without_app(self, app_name): - app_config = self._begin_without_app(app_name) - try: - yield - finally: - self._end_without_app(app_config) - - def _begin_empty(self): - app_configs, self.app_configs = self.app_configs, OrderedDict() - return app_configs - - def _end_empty(self, app_configs): - self.app_configs = app_configs - - @contextmanager - def _empty(self): - app_configs = self._begin_empty() - try: - yield - finally: - self._end_empty(app_configs) - - ### DEPRECATED METHODS GO BELOW THIS LINE ### - - def load_app(self, app_name): - """ - Loads the app with the provided fully qualified name, and returns the - model module. - """ - warnings.warn( - "load_app(app_name) is deprecated.", - PendingDeprecationWarning, stacklevel=2) - app_config = AppConfig.create(app_name) - app_config.import_models(self.all_models[app_config.label]) - self.app_configs[app_config.label] = app_config - return app_config.models_module - - def get_app(self, app_label): - """ - Returns the module containing the models for the given app_label. - - Raises UnavailableApp when set_available_apps() in in effect and - doesn't include app_label. - """ - warnings.warn( - "get_app_config(app_label).models_module supersedes get_app(app_label).", - PendingDeprecationWarning, stacklevel=2) - try: - return self.get_app_config( - app_label, only_with_models_module=True).models_module - except LookupError as exc: - # Change the exception type for backwards compatibility. - raise ImproperlyConfigured(*exc.args) - - def get_apps(self): - """ - Returns a list of all installed modules that contain models. - """ - warnings.warn( - "[a.models_module for a in get_app_configs()] supersedes get_apps().", - PendingDeprecationWarning, stacklevel=2) - app_configs = self.get_app_configs(only_with_models_module=True) - return [app_config.models_module for app_config in app_configs] - - def _get_app_package(self, app): - return '.'.join(app.__name__.split('.')[:-1]) - - def get_app_package(self, app_label): - warnings.warn( - "get_app_config(label).name supersedes get_app_package(label).", - PendingDeprecationWarning, stacklevel=2) - return self._get_app_package(self.get_app(app_label)) - - def _get_app_path(self, app): - if hasattr(app, '__path__'): # models/__init__.py package - app_path = app.__path__[0] - else: # models.py module - app_path = app.__file__ - return os.path.dirname(upath(app_path)) - - def get_app_path(self, app_label): - warnings.warn( - "get_app_config(label).path supersedes get_app_path(label).", - PendingDeprecationWarning, stacklevel=2) - return self._get_app_path(self.get_app(app_label)) - - 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.) - """ - warnings.warn( - "[a.path for a in get_app_configs()] supersedes get_app_paths().", - PendingDeprecationWarning, stacklevel=2) - - self.populate_models() - - app_paths = [] - for app in self.get_apps(): - app_paths.append(self._get_app_path(app)) - return app_paths - - def register_models(self, app_label, *models): - """ - Register a set of models as belonging to an app. - """ - warnings.warn( - "register_models(app_label, *models) is deprecated.", - PendingDeprecationWarning, stacklevel=2) - for model in models: - self.register_model(app_label, model) - - -app_cache = AppCache(master=True) diff --git a/django/core/checks/compatibility/django_1_6_0.py b/django/core/checks/compatibility/django_1_6_0.py index fef8bc3a51..a42249de60 100644 --- a/django/core/checks/compatibility/django_1_6_0.py +++ b/django/core/checks/compatibility/django_1_6_0.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals -from django.core.apps import app_cache +from django.apps import app_cache from django.db import models diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py index a7d074e149..bc81b8f9d2 100644 --- a/django/core/management/__init__.py +++ b/django/core/management/__init__.py @@ -117,7 +117,7 @@ def get_commands(): # Populate the app cache outside of the try/except block to avoid # catching ImproperlyConfigured errors that aren't caused by the # absence of a settings module. - from django.core.apps import app_cache + from django.apps import app_cache app_configs = app_cache.get_app_configs() apps = [app_config.name for app_config in app_configs] @@ -346,7 +346,7 @@ class ManagementUtility(object): elif cwords[0] in ('dumpdata', 'sql', 'sqlall', 'sqlclear', 'sqlcustom', 'sqlindexes', 'sqlsequencereset', 'test'): try: - from django.core.apps import app_cache + from django.apps import app_cache app_configs = app_cache.get_app_configs() # Get the last part of the dotted path as the app name. options += [(app_config.label, 0) for app_config in app_configs] diff --git a/django/core/management/base.py b/django/core/management/base.py index b9404ec1aa..101a486b40 100644 --- a/django/core/management/base.py +++ b/django/core/management/base.py @@ -341,7 +341,7 @@ class AppCommand(BaseCommand): args = '' def handle(self, *app_labels, **options): - from django.core.apps import app_cache + from django.apps import app_cache if not app_labels: raise CommandError('Enter at least one appname.') # Populate models and don't use only_with_models_module=True when diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index fa657bcd72..9aebb6c7d6 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -37,7 +37,7 @@ class Command(BaseCommand): args = '[appname appname.ModelName ...]' def handle(self, *app_labels, **options): - from django.core.apps import app_cache + from django.apps import app_cache format = options.get('format') indent = options.get('indent') @@ -162,7 +162,7 @@ def sort_dependencies(app_list): is serialized before a normal model, and any model with a natural key dependency has it's dependencies serialized first. """ - from django.core.apps import app_cache + from django.apps import app_cache # Process the list of models, and get the list of dependencies model_dependencies = [] models = set() diff --git a/django/core/management/commands/flush.py b/django/core/management/commands/flush.py index f13e948ae5..49007bf0a2 100644 --- a/django/core/management/commands/flush.py +++ b/django/core/management/commands/flush.py @@ -2,7 +2,7 @@ import sys from importlib import import_module from optparse import make_option -from django.core.apps import app_cache +from django.apps import app_cache from django.db import connections, router, transaction, DEFAULT_DB_ALIAS from django.core.management import call_command from django.core.management.base import NoArgsCommand, CommandError diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py index ee88232d9f..bfeba68aa6 100644 --- a/django/core/management/commands/loaddata.py +++ b/django/core/management/commands/loaddata.py @@ -7,8 +7,8 @@ import warnings import zipfile from optparse import make_option +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.core import serializers from django.core.management.base import BaseCommand, CommandError from django.core.management.color import no_style diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py index 3bd7ad42be..aaf0270840 100644 --- a/django/core/management/commands/makemigrations.py +++ b/django/core/management/commands/makemigrations.py @@ -3,7 +3,7 @@ import os import operator from optparse import make_option -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management.base import BaseCommand, CommandError from django.db import connections, DEFAULT_DB_ALIAS, migrations from django.db.migrations.loader import MigrationLoader diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py index c99f26aa0c..05b4a62e87 100644 --- a/django/core/management/commands/migrate.py +++ b/django/core/management/commands/migrate.py @@ -6,7 +6,7 @@ from importlib import import_module import itertools import traceback -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management import call_command from django.core.management.base import BaseCommand, CommandError from django.core.management.color import no_style diff --git a/django/core/management/commands/shell.py b/django/core/management/commands/shell.py index 5c189ac980..12af814161 100644 --- a/django/core/management/commands/shell.py +++ b/django/core/management/commands/shell.py @@ -66,7 +66,7 @@ class Command(NoArgsCommand): def handle_noargs(self, **options): # XXX: (Temporary) workaround for ticket #1796: force early loading of all # models from installed apps. - from django.core.apps import app_cache + from django.apps import app_cache app_cache.get_models() use_plain = options.get('plain', False) diff --git a/django/core/management/commands/sqlsequencereset.py b/django/core/management/commands/sqlsequencereset.py index cc35030a91..24ec25e8ed 100644 --- a/django/core/management/commands/sqlsequencereset.py +++ b/django/core/management/commands/sqlsequencereset.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals from optparse import make_option -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management.base import AppCommand from django.db import connections, DEFAULT_DB_ALIAS diff --git a/django/core/management/sql.py b/django/core/management/sql.py index 0b6e38124e..b2500d3787 100644 --- a/django/core/management/sql.py +++ b/django/core/management/sql.py @@ -5,8 +5,8 @@ import os import re import warnings +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.core.management.base import CommandError from django.db import models, router diff --git a/django/core/management/validation.py b/django/core/management/validation.py index 1cedcb9925..2b27a7edce 100644 --- a/django/core/management/validation.py +++ b/django/core/management/validation.py @@ -26,7 +26,7 @@ def get_validation_errors(outfile, app=None): validates all models of all installed apps. Writes errors, if any, to outfile. Returns number of errors. """ - from django.core.apps import app_cache + from django.apps import app_cache from django.db import connection, models from django.db.models.deletion import SET_NULL, SET_DEFAULT diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py index b0bc8138ab..d516656a69 100644 --- a/django/core/serializers/base.py +++ b/django/core/serializers/base.py @@ -3,7 +3,7 @@ Module for abstract serializer/unserializer base classes. """ import warnings -from django.core.apps import app_cache +from django.apps import app_cache from django.db import models from django.utils import six diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index 1e4c37e2ae..c8a2b7eff2 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -5,8 +5,8 @@ other serializers. """ from __future__ import unicode_literals +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.core.serializers import base from django.db import models, DEFAULT_DB_ALIAS from django.utils.encoding import smart_text, is_protected_type diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index 90ad2cf398..e9bea84bb1 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -4,8 +4,8 @@ XML serializer. from __future__ import unicode_literals +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.core.serializers import base from django.db import models, DEFAULT_DB_ALIAS from django.utils.xmlutils import SimplerXMLGenerator diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index adf3b236ac..86905afe77 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -1268,7 +1268,7 @@ class BaseDatabaseIntrospection(object): If only_existing is True, the resulting list will only include the tables that actually exist in the database. """ - from django.core.apps import app_cache + from django.apps import app_cache from django.db import router tables = set() for app_config in app_cache.get_app_configs(only_with_models_module=True): @@ -1289,7 +1289,7 @@ class BaseDatabaseIntrospection(object): def installed_models(self, tables): "Returns a set of all models represented by the provided list of table names." - from django.core.apps import app_cache + from django.apps import app_cache from django.db import router all_models = [] for app_config in app_cache.get_app_configs(only_with_models_module=True): @@ -1302,7 +1302,7 @@ class BaseDatabaseIntrospection(object): def sequence_list(self): "Returns a list of information about all DB sequences for all models in all apps." - from django.core.apps import app_cache + from django.apps import app_cache from django.db import models, router sequence_list = [] diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py index e2b9603819..52ca2de8ed 100644 --- a/django/db/backends/sqlite3/schema.py +++ b/django/db/backends/sqlite3/schema.py @@ -1,4 +1,4 @@ -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.db.backends.schema import BaseDatabaseSchemaEditor from django.db.models.fields.related import ManyToManyField diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py index 4c12e05add..9a54f14e75 100644 --- a/django/db/migrations/loader.py +++ b/django/db/migrations/loader.py @@ -2,7 +2,7 @@ from importlib import import_module import os import sys -from django.core.apps import app_cache +from django.apps import app_cache from django.db.migrations.recorder import MigrationRecorder from django.db.migrations.graph import MigrationGraph from django.utils import six diff --git a/django/db/migrations/questioner.py b/django/db/migrations/questioner.py index 8a11559993..4a860dcf7e 100644 --- a/django/db/migrations/questioner.py +++ b/django/db/migrations/questioner.py @@ -2,7 +2,7 @@ import importlib import os import sys -from django.core.apps import app_cache +from django.apps import app_cache from django.utils import datetime_safe from django.utils.six.moves import input diff --git a/django/db/migrations/recorder.py b/django/db/migrations/recorder.py index c2cfd2e9af..8b0403e88f 100644 --- a/django/db/migrations/recorder.py +++ b/django/db/migrations/recorder.py @@ -1,4 +1,4 @@ -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.db import models from django.utils.timezone import now diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py index c43728d58e..a2716e864a 100644 --- a/django/db/migrations/state.py +++ b/django/db/migrations/state.py @@ -1,4 +1,4 @@ -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.db import models from django.db.models.options import DEFAULT_NAMES, normalize_unique_together from django.utils import six diff --git a/django/db/migrations/writer.py b/django/db/migrations/writer.py index 04e00501f9..a23a9b1253 100644 --- a/django/db/migrations/writer.py +++ b/django/db/migrations/writer.py @@ -5,7 +5,7 @@ from importlib import import_module import os import types -from django.core.apps import app_cache +from django.apps import app_cache from django.db import models from django.db.migrations.loader import MigrationLoader from django.utils.encoding import force_text diff --git a/django/db/models/base.py b/django/db/models/base.py index 5599d81b4b..3ae0fe34bd 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -5,8 +5,8 @@ import sys from functools import update_wrapper from django.utils.six.moves import zip -from django.core.apps import app_cache -from django.core.apps.base import MODELS_MODULE_NAME +from django.apps import app_cache +from django.apps.base import MODELS_MODULE_NAME import django.db.models.manager # NOQA: Imported to register signal handler. from django.conf import settings from django.core.exceptions import (ObjectDoesNotExist, diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index b24323d1cf..830ff2efa2 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -9,7 +9,7 @@ import warnings from base64 import b64decode, b64encode from itertools import tee -from django.core.apps import app_cache +from django.apps import app_cache from django.db import connection from django.db.models.query_utils import QueryWrapper from django.conf import settings diff --git a/django/db/models/loading.py b/django/db/models/loading.py index 00fae36769..4b58ba00b5 100644 --- a/django/db/models/loading.py +++ b/django/db/models/loading.py @@ -1,6 +1,6 @@ import warnings -from django.core.apps import app_cache +from django.apps import app_cache warnings.warn( "The utilities in django.db.models.loading are deprecated " diff --git a/django/db/models/options.py b/django/db/models/options.py index fec9aa4fc4..8f181c8854 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -5,8 +5,8 @@ import re from bisect import bisect import warnings +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.db.models.fields.related import ManyToManyRel from django.db.models.fields import AutoField, FieldDoesNotExist from django.db.models.fields.proxy import OrderWrt diff --git a/django/db/models/signals.py b/django/db/models/signals.py index a6822309a3..8c835e5f5f 100644 --- a/django/db/models/signals.py +++ b/django/db/models/signals.py @@ -1,6 +1,6 @@ from collections import defaultdict -from django.core.apps import app_cache +from django.apps import app_cache from django.dispatch import Signal from django.utils import six diff --git a/django/db/utils.py b/django/db/utils.py index 4d53d252bf..702b1b4ebc 100644 --- a/django/db/utils.py +++ b/django/db/utils.py @@ -282,6 +282,6 @@ class ConnectionRouter(object): """ Return app models allowed to be synchronized on provided db. """ - from django.core.apps import app_cache + from django.apps import app_cache return [model for model in app_cache.get_models(app, include_auto_created=include_auto_created) if self.allow_migrate(db, model)] diff --git a/django/template/base.py b/django/template/base.py index 7098ea60f8..197238b1e3 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -5,8 +5,8 @@ from functools import partial from importlib import import_module from inspect import getargspec, getcallargs +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.template.context import (BaseContext, Context, RequestContext, # NOQA: imported for backwards compatibility ContextPopException) from django.utils.itercompat import is_iterable diff --git a/django/template/loaders/app_directories.py b/django/template/loaders/app_directories.py index 90baa34c7a..ff3d3b93f8 100644 --- a/django/template/loaders/app_directories.py +++ b/django/template/loaders/app_directories.py @@ -6,8 +6,8 @@ packages. import os import sys +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.template.base import TemplateDoesNotExist from django.template.loader import BaseLoader from django.utils._os import safe_join diff --git a/django/template/loaders/eggs.py b/django/template/loaders/eggs.py index e9b46b15de..99c19aed93 100644 --- a/django/template/loaders/eggs.py +++ b/django/template/loaders/eggs.py @@ -6,8 +6,8 @@ try: except ImportError: resource_string = None +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.template.base import TemplateDoesNotExist from django.template.loader import BaseLoader from django.utils import six diff --git a/django/test/client.py b/django/test/client.py index cccc3ecc42..eea9b43010 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -8,9 +8,9 @@ from copy import copy from importlib import import_module from io import BytesIO +from django.apps import app_cache from django.conf import settings from django.contrib.auth import authenticate, login, logout, get_user_model -from django.core.apps import app_cache from django.core.handlers.base import BaseHandler from django.core.handlers.wsgi import WSGIRequest from django.core.signals import (request_started, request_finished, diff --git a/django/test/simple.py b/django/test/simple.py index 6129ce1305..f2d26376df 100644 --- a/django/test/simple.py +++ b/django/test/simple.py @@ -9,7 +9,7 @@ import re import unittest as real_unittest import warnings -from django.core.apps import app_cache +from django.apps import app_cache from django.test import _doctest as doctest from django.test import runner from django.test.utils import compare_xml, strip_quotes diff --git a/django/test/testcases.py b/django/test/testcases.py index 13f56fa6cc..1480889565 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -15,9 +15,9 @@ import unittest from unittest import skipIf # NOQA: Imported here for backward compatibility from unittest.util import safe_repr +from django.apps import app_cache from django.conf import settings from django.core import mail -from django.core.apps import app_cache from django.core.exceptions import ValidationError, ImproperlyConfigured from django.core.handlers.wsgi import get_path_info, WSGIHandler from django.core.management import call_command diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index 05ffb12f74..b7a889aa61 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -36,8 +36,8 @@ import sys import time import traceback +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.core.signals import request_finished try: from django.utils.six.moves import _thread as thread diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py index 8d95fc00a3..c7826be5e5 100644 --- a/django/utils/module_loading.py +++ b/django/utils/module_loading.py @@ -58,7 +58,7 @@ def autodiscover_modules(*args, **kwargs): registry. This register_to object must have a _registry instance variable to access it. """ - from django.core.apps import app_cache + from django.apps import app_cache register_to = kwargs.get('register_to') for app_config in app_cache.get_app_configs(): diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 3ed6371966..1eced98d31 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -10,7 +10,7 @@ import gettext as gettext_module from threading import local import warnings -from django.core.apps import app_cache +from django.apps import app_cache from django.dispatch import receiver from django.test.signals import setting_changed from django.utils.encoding import force_str, force_text diff --git a/django/views/i18n.py b/django/views/i18n.py index 2f0c89a037..2cc2e35e5e 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -4,8 +4,8 @@ import os import gettext as gettext_module from django import http +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.template import Context, Template from django.utils.translation import check_for_language, to_locale, get_language from django.utils.encoding import smart_text diff --git a/tests/admin_docs/tests.py b/tests/admin_docs/tests.py index 66c125490f..9e004a5a07 100644 --- a/tests/admin_docs/tests.py +++ b/tests/admin_docs/tests.py @@ -1,10 +1,10 @@ import unittest +from django.apps import app_cache from django.conf import settings from django.contrib.sites.models import Site from django.contrib.admindocs import utils from django.contrib.auth.models import User -from django.core.apps import app_cache from django.core.urlresolvers import reverse from django.test import TestCase from django.test.utils import override_settings diff --git a/tests/app_cache/models.py b/tests/app_cache/models.py index 10e9e6f1de..9306830f9c 100644 --- a/tests/app_cache/models.py +++ b/tests/app_cache/models.py @@ -1,4 +1,4 @@ -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.db import models # We're testing app cache presence on load, so this is handy. diff --git a/tests/app_cache/tests.py b/tests/app_cache/tests.py index a531a22e8b..43133ab38f 100644 --- a/tests/app_cache/tests.py +++ b/tests/app_cache/tests.py @@ -1,7 +1,7 @@ from __future__ import absolute_import -from django.core.apps import app_cache -from django.core.apps.cache import AppCache +from django.apps import app_cache +from django.apps.cache import AppCache from django.db import models from django.test import TestCase diff --git a/tests/app_loading/tests.py b/tests/app_loading/tests.py index dcd0fa34c0..0692597a5b 100644 --- a/tests/app_loading/tests.py +++ b/tests/app_loading/tests.py @@ -5,8 +5,8 @@ import sys from unittest import TestCase import warnings -from django.core.apps import app_cache -from django.core.apps.cache import AppCache +from django.apps import app_cache +from django.apps.cache import AppCache from django.test.utils import override_settings from django.utils._os import upath from django.utils import six diff --git a/tests/bash_completion/tests.py b/tests/bash_completion/tests.py index 85fb58904c..5a6a6c48d2 100644 --- a/tests/bash_completion/tests.py +++ b/tests/bash_completion/tests.py @@ -5,7 +5,7 @@ import os import sys import unittest -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management import ManagementUtility from django.utils.six import StringIO diff --git a/tests/commands_sql/tests.py b/tests/commands_sql/tests.py index 3088ea4d48..1c2a7f0ffa 100644 --- a/tests/commands_sql/tests.py +++ b/tests/commands_sql/tests.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management.color import no_style from django.core.management.sql import (sql_create, sql_delete, sql_indexes, sql_destroy_indexes, sql_all) diff --git a/tests/comment_tests/tests/test_app_api.py b/tests/comment_tests/tests/test_app_api.py index 645daf123d..7098def28a 100644 --- a/tests/comment_tests/tests/test_app_api.py +++ b/tests/comment_tests/tests/test_app_api.py @@ -1,8 +1,8 @@ +from django.apps import app_cache from django.conf import settings from django.contrib import comments from django.contrib.comments.models import Comment from django.contrib.comments.forms import CommentForm -from django.core.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django.test.utils import override_settings from django.utils import six diff --git a/tests/contenttypes_tests/tests.py b/tests/contenttypes_tests/tests.py index 9cc254e665..d3c19fd910 100644 --- a/tests/contenttypes_tests/tests.py +++ b/tests/contenttypes_tests/tests.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals +from django.apps.cache import AppCache from django.contrib.contenttypes.models import ContentType -from django.core.apps.cache import AppCache from django.db import models from django.test import TestCase diff --git a/tests/defer_regress/tests.py b/tests/defer_regress/tests.py index 3e9651b2d2..442af9f7cf 100644 --- a/tests/defer_regress/tests.py +++ b/tests/defer_regress/tests.py @@ -2,9 +2,9 @@ from __future__ import unicode_literals from operator import attrgetter +from django.apps import app_cache from django.contrib.contenttypes.models import ContentType from django.contrib.sessions.backends.db import SessionStore -from django.core.apps import app_cache from django.db.models import Count from django.test import TestCase from django.test.utils import override_settings diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 339317c541..8d8b5fbe9c 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -8,8 +8,8 @@ import os import pickle from threading import local +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.template import Template, Context from django.template.base import TemplateSyntaxError from django.test import TestCase, RequestFactory diff --git a/tests/invalid_models_tests/tests.py b/tests/invalid_models_tests/tests.py index 4e0cef546b..09c19d453c 100644 --- a/tests/invalid_models_tests/tests.py +++ b/tests/invalid_models_tests/tests.py @@ -1,7 +1,7 @@ import sys import unittest -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management.validation import get_validation_errors from django.test.utils import override_settings from django.utils.six import StringIO diff --git a/tests/managers_regress/tests.py b/tests/managers_regress/tests.py index b9c8244612..9d7e0d8174 100644 --- a/tests/managers_regress/tests.py +++ b/tests/managers_regress/tests.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals -from django.core.apps import app_cache +from django.apps import app_cache from django.db import models from django.template import Context, Template from django.test import TestCase diff --git a/tests/migrations/models.py b/tests/migrations/models.py index cfc9604551..b1ef6c1dd1 100644 --- a/tests/migrations/models.py +++ b/tests/migrations/models.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.db import models from django.utils.encoding import python_2_unicode_compatible diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index 13514cac91..fcb460decc 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -5,7 +5,7 @@ import codecs import os import shutil -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management import call_command, CommandError from django.test.utils import override_settings from django.utils import six diff --git a/tests/migrations/test_state.py b/tests/migrations/test_state.py index 7a06ecd474..e695248cd2 100644 --- a/tests/migrations/test_state.py +++ b/tests/migrations/test_state.py @@ -1,4 +1,4 @@ -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.db import models from django.db.migrations.state import ProjectState, ModelState, InvalidBasesError from django.test import TestCase diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py index 3f46703207..df3d052610 100644 --- a/tests/migrations/test_writer.py +++ b/tests/migrations/test_writer.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import datetime import os -from django.core.apps import app_cache +from django.apps import app_cache from django.core.validators import RegexValidator, EmailValidator from django.db import models, migrations from django.db.migrations.writer import MigrationWriter diff --git a/tests/no_models/tests.py b/tests/no_models/tests.py index 34ef724446..f9ff80485e 100644 --- a/tests/no_models/tests.py +++ b/tests/no_models/tests.py @@ -1,4 +1,4 @@ -from django.core.apps import app_cache +from django.apps import app_cache from django.test import TestCase diff --git a/tests/proxy_model_inheritance/tests.py b/tests/proxy_model_inheritance/tests.py index 5f33ec2fee..c0b564746d 100644 --- a/tests/proxy_model_inheritance/tests.py +++ b/tests/proxy_model_inheritance/tests.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import os import sys -from django.core.apps import app_cache +from django.apps import app_cache from django.core.management import call_command from django.test import TestCase, TransactionTestCase from django.utils._os import upath diff --git a/tests/proxy_models/tests.py b/tests/proxy_models/tests.py index 0995a778c0..800fc42e6d 100644 --- a/tests/proxy_models/tests.py +++ b/tests/proxy_models/tests.py @@ -1,9 +1,9 @@ from __future__ import unicode_literals +from django.apps import app_cache from django.contrib import admin from django.contrib.contenttypes.models import ContentType from django.core import management -from django.core.apps import app_cache from django.core.exceptions import FieldError from django.db import models, DEFAULT_DB_ALIAS from django.db.models import signals diff --git a/tests/runtests.py b/tests/runtests.py index 64d363a095..88973308cf 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -80,14 +80,14 @@ def get_test_modules(): def get_installed(): - from django.core.apps import app_cache + from django.apps import app_cache return [app_config.name for app_config in app_cache.get_app_configs()] def setup(verbosity, test_labels): import django + from django.apps import app_cache from django.conf import settings - from django.core.apps import app_cache from django.test import TransactionTestCase, TestCase print("Testing against Django installed in '%s'" % os.path.dirname(django.__file__)) diff --git a/tests/schema/models.py b/tests/schema/models.py index 8b24b88c05..b294647f9b 100644 --- a/tests/schema/models.py +++ b/tests/schema/models.py @@ -1,4 +1,4 @@ -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.db import models # Because we want to test creation and deletion of these as separate things, diff --git a/tests/swappable_models/tests.py b/tests/swappable_models/tests.py index fec9db5af8..0beb95af3e 100644 --- a/tests/swappable_models/tests.py +++ b/tests/swappable_models/tests.py @@ -2,9 +2,9 @@ from __future__ import unicode_literals from django.utils.six import StringIO +from django.apps import app_cache from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType -from django.core.apps import app_cache from django.core import management from django.test import TestCase from django.test.utils import override_settings diff --git a/tests/tablespaces/tests.py b/tests/tablespaces/tests.py index fa90704c45..d761a93ab9 100644 --- a/tests/tablespaces/tests.py +++ b/tests/tablespaces/tests.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.db import connection from django.core.management.color import no_style from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature diff --git a/tests/template_tests/test_loaders.py b/tests/template_tests/test_loaders.py index 551bd7fb72..eadb3fb02a 100644 --- a/tests/template_tests/test_loaders.py +++ b/tests/template_tests/test_loaders.py @@ -20,7 +20,7 @@ except ImportError: pkg_resources = None -from django.core.apps import app_cache +from django.apps import app_cache from django.template import TemplateDoesNotExist, Context from django.template.loaders.eggs import Loader as EggLoader from django.template import loader diff --git a/tests/template_tests/tests.py b/tests/template_tests/tests.py index 61a46a81f9..4dc0925070 100644 --- a/tests/template_tests/tests.py +++ b/tests/template_tests/tests.py @@ -16,7 +16,7 @@ import unittest import warnings from django import template -from django.core.apps import app_cache +from django.apps import app_cache from django.core import urlresolvers from django.template import (base as template_base, loader, Context, RequestContext, Template, TemplateSyntaxError) diff --git a/tests/test_runner/tests.py b/tests/test_runner/tests.py index 3c365b0225..5393ea75a2 100644 --- a/tests/test_runner/tests.py +++ b/tests/test_runner/tests.py @@ -224,7 +224,7 @@ class ModulesTestsPackages(IgnoreAllDeprecationWarningsMixin, unittest.TestCase) def test_get_tests(self): "Check that the get_tests helper function can find tests in a directory" - from django.core.apps.base import AppConfig + from django.apps.base import AppConfig from django.test.simple import get_tests app_config = AppConfig.create('test_runner.valid_app') app_config.import_models({}) @@ -233,7 +233,7 @@ class ModulesTestsPackages(IgnoreAllDeprecationWarningsMixin, unittest.TestCase) def test_import_error(self): "Test for #12658 - Tests with ImportError's shouldn't fail silently" - from django.core.apps.base import AppConfig + from django.apps.base import AppConfig from django.test.simple import get_tests app_config = AppConfig.create('test_runner_invalid_app') app_config.import_models({}) diff --git a/tests/test_suite_override/tests.py b/tests/test_suite_override/tests.py index b464659275..9666df1c19 100644 --- a/tests/test_suite_override/tests.py +++ b/tests/test_suite_override/tests.py @@ -1,6 +1,6 @@ import unittest -from django.core.apps import app_cache +from django.apps import app_cache from django.test.utils import IgnoreAllDeprecationWarningsMixin diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py index 47c70fae92..5071566e92 100644 --- a/tests/utils_tests/test_autoreload.py +++ b/tests/utils_tests/test_autoreload.py @@ -1,8 +1,8 @@ import os from django import conf +from django.apps import app_cache from django.contrib import admin -from django.core.apps import app_cache from django.test import TestCase, override_settings from django.utils.autoreload import gen_filenames diff --git a/tests/utils_tests/test_module_loading.py b/tests/utils_tests/test_module_loading.py index 0c8dfe1e12..baaab36494 100644 --- a/tests/utils_tests/test_module_loading.py +++ b/tests/utils_tests/test_module_loading.py @@ -5,7 +5,7 @@ import sys import unittest from zipimport import zipimporter -from django.core.apps import app_cache +from django.apps import app_cache from django.core.exceptions import ImproperlyConfigured from django.test import SimpleTestCase from django.utils import six diff --git a/tests/validation/test_unique.py b/tests/validation/test_unique.py index f05256a6f1..be7808f460 100644 --- a/tests/validation/test_unique.py +++ b/tests/validation/test_unique.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import datetime import unittest -from django.core.apps.cache import AppCache +from django.apps.cache import AppCache from django.core.exceptions import ValidationError from django.db import models from django.test import TestCase diff --git a/tests/view_tests/tests/test_i18n.py b/tests/view_tests/tests/test_i18n.py index 19bbde286c..1e4eff66df 100644 --- a/tests/view_tests/tests/test_i18n.py +++ b/tests/view_tests/tests/test_i18n.py @@ -4,8 +4,8 @@ import os from os import path import unittest +from django.apps import app_cache from django.conf import settings -from django.core.apps import app_cache from django.core.urlresolvers import reverse from django.test import LiveServerTestCase, TestCase from django.test.utils import override_settings -- cgit v1.3