Commit b355e98a authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

Normalized exceptions raised by AppConfig.create.

It raises ImportError whenever an entry in INSTALLED_APPS points
(directly or indirectly via AppConfig.name) to a non-existing module
and ImproperlyConfigured in all other cases.

Catching ImportError and re-raising ImproperlyConfigured tends to make
circular imports more difficult to diagnose.
parent ce1bc2c9
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
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.module_loading import module_has_submodule
from django.utils._os import upath


@@ -66,13 +66,24 @@ class AppConfig(object):
            module = import_module(entry)

        except ImportError:
            # Avoid django.utils.module_loading.import_by_path because it
            # masks errors -- it reraises ImportError as ImproperlyConfigured.
            mod_path, _, cls_name = entry.rpartition('.')

            # 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:
            # app config class.
            if not mod_path:
                raise

            cls = import_by_path(entry)
            mod = import_module(mod_path)
            try:
                cls = getattr(mod, cls_name)
            except AttributeError:
                # Emulate the error that "from <mod_path> import <cls_name>"
                # would raise when <mod_path> exists but not <cls_name>, with
                # more context (Python just says "cannot import name ...").
                raise ImportError(
                    "cannot import name %r from %r" % (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.)