From 4f03b718f712b39f306f6dfe177e1f65b5437ac2 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sun, 26 Jan 2014 13:17:03 +0100 Subject: Fixed #21877 -- Renamed django.apps.base to config. --- django/apps/__init__.py | 2 +- django/apps/base.py | 185 ----------------------------------------------- django/apps/config.py | 185 +++++++++++++++++++++++++++++++++++++++++++++++ django/apps/registry.py | 2 +- django/db/models/base.py | 2 +- 5 files changed, 188 insertions(+), 188 deletions(-) delete mode 100644 django/apps/base.py create mode 100644 django/apps/config.py diff --git a/django/apps/__init__.py b/django/apps/__init__.py index 074a448660..de0f303846 100644 --- a/django/apps/__init__.py +++ b/django/apps/__init__.py @@ -1,2 +1,2 @@ -from .base import AppConfig # NOQA +from .config import AppConfig # NOQA from .registry import apps # NOQA diff --git a/django/apps/base.py b/django/apps/base.py deleted file mode 100644 index e25178e25d..0000000000 --- a/django/apps/base.py +++ /dev/null @@ -1,185 +0,0 @@ -from importlib import import_module - -from django.core.exceptions import ImproperlyConfigured -from django.utils.module_loading import 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, app_module): - # Full Python path to the application eg. 'django.contrib.admin'. - self.name = app_name - - # Root module for the application eg. . - self.module = app_module - - # 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: - paths = app_module.__path__ - except AttributeError: - self.path = None - else: - # Convert paths to list because Python 3.3 _NamespacePath does - # not support indexing. - paths = list(paths) - if len(paths) > 1: - raise ImproperlyConfigured( - "The namespace package app %r has multiple locations, " - "which is not supported: %r" % (app_name, paths)) - self.path = upath(paths[0]) - - # 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 '<%s: %s>' % (self.__class__.__name__, 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, - # which may specify an app config class with default_app_config. - # Otherwise, entry is a path to an app config class or an error. - module = import_module(entry) - - except ImportError: - mod_path, _, cls_name = entry.rpartition('.') - - # Raise the original exception when entry cannot be a path to an - # app config class. - if not mod_path: - raise - - else: - try: - # If this works, the app module specifies an app config class. - entry = module.default_app_config - except AttributeError: - # Otherwise, it simply uses the default app config class. - return cls(entry, module) - else: - mod_path, _, cls_name = entry.rpartition('.') - - # If we're reaching this point, we must load the app config class - # located at .. - - # Avoid django.utils.module_loading.import_by_path because it - # masks errors -- it reraises ImportError as ImproperlyConfigured. - mod = import_module(mod_path) - try: - cls = getattr(mod, cls_name) - except AttributeError: - # Emulate the error that "from import " - # would raise when exists but not , with - # more context (Python just says "cannot import name ..."). - raise ImportError( - "cannot import name '%s' from '%s'" % (cls_name, mod_path)) - - # 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( - "'%s' 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( - "'%s' must supply a name attribute." % entry) - - # Ensure app_name points to a valid module. - app_module = import_module(app_name) - - # Entry is a path to an app config class. - return cls(app_name, app_module) - - - def get_model(self, model_name): - """ - Returns the model with the given case-insensitive model_name. - - Raises LookupError if no model exists with this name. - """ - if self.models is None: - raise LookupError( - "App '%s' doesn't have any models." % self.label) - try: - return self.models[model_name.lower()] - except KeyError: - raise LookupError( - "App '%s' doesn't have a '%s' model." % (self.label, model_name)) - - def get_models(self, include_auto_created=False, - include_deferred=False, include_swapped=False): - """ - Returns an iterable of models. - - By default, the following models aren't included: - - - auto-created models for many-to-many relations without - an explicit intermediate table, - - models created to satisfy deferred attribute queries, - - models that have been swapped out. - - Set the corresponding keyword argument to True to include such models. - Keyword arguments aren't documented; they're a private API. - """ - for model in self.models.values(): - if model._deferred and not include_deferred: - continue - if model._meta.auto_created and not include_auto_created: - continue - if model._meta.swapped and not include_swapped: - continue - yield model - - def import_models(self, all_models): - # Dictionary of models for this app, primarily maintained in the - # 'all_models' attribute of the Apps this AppConfig is attached to. - # Injected as a parameter because it gets populated when models are - # imported, which might happen before populate() imports models. - self.models = all_models - - if module_has_submodule(self.module, MODELS_MODULE_NAME): - models_module_name = '%s.%s' % (self.name, MODELS_MODULE_NAME) - self.models_module = import_module(models_module_name) - - def ready(self): - """ - Override this method in subclasses to run code when Django starts. - """ diff --git a/django/apps/config.py b/django/apps/config.py new file mode 100644 index 0000000000..e25178e25d --- /dev/null +++ b/django/apps/config.py @@ -0,0 +1,185 @@ +from importlib import import_module + +from django.core.exceptions import ImproperlyConfigured +from django.utils.module_loading import 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, app_module): + # Full Python path to the application eg. 'django.contrib.admin'. + self.name = app_name + + # Root module for the application eg. . + self.module = app_module + + # 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: + paths = app_module.__path__ + except AttributeError: + self.path = None + else: + # Convert paths to list because Python 3.3 _NamespacePath does + # not support indexing. + paths = list(paths) + if len(paths) > 1: + raise ImproperlyConfigured( + "The namespace package app %r has multiple locations, " + "which is not supported: %r" % (app_name, paths)) + self.path = upath(paths[0]) + + # 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 '<%s: %s>' % (self.__class__.__name__, 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, + # which may specify an app config class with default_app_config. + # Otherwise, entry is a path to an app config class or an error. + module = import_module(entry) + + except ImportError: + mod_path, _, cls_name = entry.rpartition('.') + + # Raise the original exception when entry cannot be a path to an + # app config class. + if not mod_path: + raise + + else: + try: + # If this works, the app module specifies an app config class. + entry = module.default_app_config + except AttributeError: + # Otherwise, it simply uses the default app config class. + return cls(entry, module) + else: + mod_path, _, cls_name = entry.rpartition('.') + + # If we're reaching this point, we must load the app config class + # located at .. + + # Avoid django.utils.module_loading.import_by_path because it + # masks errors -- it reraises ImportError as ImproperlyConfigured. + mod = import_module(mod_path) + try: + cls = getattr(mod, cls_name) + except AttributeError: + # Emulate the error that "from import " + # would raise when exists but not , with + # more context (Python just says "cannot import name ..."). + raise ImportError( + "cannot import name '%s' from '%s'" % (cls_name, mod_path)) + + # 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( + "'%s' 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( + "'%s' must supply a name attribute." % entry) + + # Ensure app_name points to a valid module. + app_module = import_module(app_name) + + # Entry is a path to an app config class. + return cls(app_name, app_module) + + + def get_model(self, model_name): + """ + Returns the model with the given case-insensitive model_name. + + Raises LookupError if no model exists with this name. + """ + if self.models is None: + raise LookupError( + "App '%s' doesn't have any models." % self.label) + try: + return self.models[model_name.lower()] + except KeyError: + raise LookupError( + "App '%s' doesn't have a '%s' model." % (self.label, model_name)) + + def get_models(self, include_auto_created=False, + include_deferred=False, include_swapped=False): + """ + Returns an iterable of models. + + By default, the following models aren't included: + + - auto-created models for many-to-many relations without + an explicit intermediate table, + - models created to satisfy deferred attribute queries, + - models that have been swapped out. + + Set the corresponding keyword argument to True to include such models. + Keyword arguments aren't documented; they're a private API. + """ + for model in self.models.values(): + if model._deferred and not include_deferred: + continue + if model._meta.auto_created and not include_auto_created: + continue + if model._meta.swapped and not include_swapped: + continue + yield model + + def import_models(self, all_models): + # Dictionary of models for this app, primarily maintained in the + # 'all_models' attribute of the Apps this AppConfig is attached to. + # Injected as a parameter because it gets populated when models are + # imported, which might happen before populate() imports models. + self.models = all_models + + if module_has_submodule(self.module, MODELS_MODULE_NAME): + models_module_name = '%s.%s' % (self.name, MODELS_MODULE_NAME) + self.models_module = import_module(models_module_name) + + def ready(self): + """ + Override this method in subclasses to run code when Django starts. + """ diff --git a/django/apps/registry.py b/django/apps/registry.py index 7cf5a2637b..601091cfb7 100644 --- a/django/apps/registry.py +++ b/django/apps/registry.py @@ -8,7 +8,7 @@ from django.core.exceptions import ImproperlyConfigured from django.utils import lru_cache from django.utils._os import upath -from .base import AppConfig +from .config import AppConfig class Apps(object): diff --git a/django/db/models/base.py b/django/db/models/base.py index 65e1f5d9e4..e689f7be8a 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -6,7 +6,7 @@ from functools import update_wrapper import warnings from django.apps import apps -from django.apps.base import MODELS_MODULE_NAME +from django.apps.config import MODELS_MODULE_NAME import django.db.models.manager # NOQA: Imported to register signal handler. from django.conf import settings from django.core import checks -- cgit v1.3