Loading django/core/apps/base.py +64 −15 Original line number Diff line number Diff line from importlib import import_module from django.utils.module_loading import module_has_submodule from django.core.exceptions import ImproperlyConfigured from django.utils.module_loading import import_by_path, module_has_submodule from django.utils._os import upath Loading @@ -14,16 +15,33 @@ class AppConfig(object): def __init__(self, app_name): # Full Python path to the application eg. 'django.contrib.admin'. # This is the value that appears in INSTALLED_APPS. self.name = app_name # Root module for the application eg. <module 'django.contrib.admin' # from 'django/contrib/admin/__init__.pyc'>. 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] # Root module eg. <module 'django.contrib.admin' from # 'django/contrib/admin/__init__.pyc'>. self.app_module = import_module(app_name) # 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. <module 'django.contrib.admin.models' # from 'django/contrib/admin/models.pyc'>. Set by import_models(). Loading @@ -34,17 +52,48 @@ class AppConfig(object): # None to prevent accidental access before import_models() runs. self.models = None # 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. def __repr__(self): return '<AppConfig: %s>' % self.label @classmethod def create(cls, entry): """ Factory that creates an app config from an entry in INSTALLED_APPS. """ try: self.path = upath(self.app_module.__path__[0]) # 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: self.path = None raise ImproperlyConfigured( "%r must supply a name attribute." % entry) def __repr__(self): return '<AppConfig: %s>' % self.label # 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' Loading django/core/apps/cache.py +3 −3 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ class AppCache(object): # especially not other application modules, even indirectly. # Therefore we simply import them sequentially. for app_name in settings.INSTALLED_APPS: app_config = AppConfig(app_name) app_config = AppConfig.create(app_name) self.app_configs[app_config.label] = app_config self._apps_loaded = True Loading Loading @@ -347,7 +347,7 @@ class AppCache(object): def _begin_with_app(self, app_name): # Returns an opaque value that can be passed to _end_with_app(). app_config = AppConfig(app_name) app_config = AppConfig.create(app_name) if app_config.label in self.app_configs: return None else: Loading Loading @@ -412,7 +412,7 @@ class AppCache(object): warnings.warn( "load_app(app_name) is deprecated.", PendingDeprecationWarning, stacklevel=2) app_config = AppConfig(app_name) 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 Loading tests/test_runner/tests.py +2 −2 Original line number Diff line number Diff line Loading @@ -226,7 +226,7 @@ class ModulesTestsPackages(IgnoreAllDeprecationWarningsMixin, unittest.TestCase) "Check that the get_tests helper function can find tests in a directory" from django.core.apps.base import AppConfig from django.test.simple import get_tests app_config = AppConfig('test_runner.valid_app') app_config = AppConfig.create('test_runner.valid_app') app_config.import_models({}) tests = get_tests(app_config) self.assertIsInstance(tests, types.ModuleType) Loading @@ -235,7 +235,7 @@ class ModulesTestsPackages(IgnoreAllDeprecationWarningsMixin, unittest.TestCase) "Test for #12658 - Tests with ImportError's shouldn't fail silently" from django.core.apps.base import AppConfig from django.test.simple import get_tests app_config = AppConfig('test_runner_invalid_app') app_config = AppConfig.create('test_runner_invalid_app') app_config.import_models({}) with self.assertRaises(ImportError): get_tests(app_config) Loading Loading
django/core/apps/base.py +64 −15 Original line number Diff line number Diff line from importlib import import_module from django.utils.module_loading import module_has_submodule from django.core.exceptions import ImproperlyConfigured from django.utils.module_loading import import_by_path, module_has_submodule from django.utils._os import upath Loading @@ -14,16 +15,33 @@ class AppConfig(object): def __init__(self, app_name): # Full Python path to the application eg. 'django.contrib.admin'. # This is the value that appears in INSTALLED_APPS. self.name = app_name # Root module for the application eg. <module 'django.contrib.admin' # from 'django/contrib/admin/__init__.pyc'>. 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] # Root module eg. <module 'django.contrib.admin' from # 'django/contrib/admin/__init__.pyc'>. self.app_module = import_module(app_name) # 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. <module 'django.contrib.admin.models' # from 'django/contrib/admin/models.pyc'>. Set by import_models(). Loading @@ -34,17 +52,48 @@ class AppConfig(object): # None to prevent accidental access before import_models() runs. self.models = None # 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. def __repr__(self): return '<AppConfig: %s>' % self.label @classmethod def create(cls, entry): """ Factory that creates an app config from an entry in INSTALLED_APPS. """ try: self.path = upath(self.app_module.__path__[0]) # 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: self.path = None raise ImproperlyConfigured( "%r must supply a name attribute." % entry) def __repr__(self): return '<AppConfig: %s>' % self.label # 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' Loading
django/core/apps/cache.py +3 −3 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ class AppCache(object): # especially not other application modules, even indirectly. # Therefore we simply import them sequentially. for app_name in settings.INSTALLED_APPS: app_config = AppConfig(app_name) app_config = AppConfig.create(app_name) self.app_configs[app_config.label] = app_config self._apps_loaded = True Loading Loading @@ -347,7 +347,7 @@ class AppCache(object): def _begin_with_app(self, app_name): # Returns an opaque value that can be passed to _end_with_app(). app_config = AppConfig(app_name) app_config = AppConfig.create(app_name) if app_config.label in self.app_configs: return None else: Loading Loading @@ -412,7 +412,7 @@ class AppCache(object): warnings.warn( "load_app(app_name) is deprecated.", PendingDeprecationWarning, stacklevel=2) app_config = AppConfig(app_name) 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 Loading
tests/test_runner/tests.py +2 −2 Original line number Diff line number Diff line Loading @@ -226,7 +226,7 @@ class ModulesTestsPackages(IgnoreAllDeprecationWarningsMixin, unittest.TestCase) "Check that the get_tests helper function can find tests in a directory" from django.core.apps.base import AppConfig from django.test.simple import get_tests app_config = AppConfig('test_runner.valid_app') app_config = AppConfig.create('test_runner.valid_app') app_config.import_models({}) tests = get_tests(app_config) self.assertIsInstance(tests, types.ModuleType) Loading @@ -235,7 +235,7 @@ class ModulesTestsPackages(IgnoreAllDeprecationWarningsMixin, unittest.TestCase) "Test for #12658 - Tests with ImportError's shouldn't fail silently" from django.core.apps.base import AppConfig from django.test.simple import get_tests app_config = AppConfig('test_runner_invalid_app') app_config = AppConfig.create('test_runner_invalid_app') app_config.import_models({}) with self.assertRaises(ImportError): get_tests(app_config) Loading