Factory that creates an app config from an entry in INSTALLED_APPS.
(cls, entry)
| 98 | |
| 99 | @classmethod |
| 100 | def create(cls, entry): |
| 101 | """ |
| 102 | Factory that creates an app config from an entry in INSTALLED_APPS. |
| 103 | """ |
| 104 | # create() eventually returns app_config_class(app_name, app_module). |
| 105 | app_config_class = None |
| 106 | app_name = None |
| 107 | app_module = None |
| 108 | |
| 109 | # If import_module succeeds, entry points to the app module. |
| 110 | try: |
| 111 | app_module = import_module(entry) |
| 112 | except Exception: |
| 113 | pass |
| 114 | else: |
| 115 | # If app_module has an apps submodule that defines a single |
| 116 | # AppConfig subclass, use it automatically. |
| 117 | # To prevent this, an AppConfig subclass can declare a class |
| 118 | # variable default = False. |
| 119 | # If the apps module defines more than one AppConfig subclass, |
| 120 | # the default one can declare default = True. |
| 121 | if module_has_submodule(app_module, APPS_MODULE_NAME): |
| 122 | mod_path = "%s.%s" % (entry, APPS_MODULE_NAME) |
| 123 | mod = import_module(mod_path) |
| 124 | # Check if there's exactly one AppConfig candidate, |
| 125 | # excluding those that explicitly define default = False. |
| 126 | app_configs = [ |
| 127 | (name, candidate) |
| 128 | for name, candidate in inspect.getmembers(mod, inspect.isclass) |
| 129 | if ( |
| 130 | issubclass(candidate, cls) |
| 131 | and candidate is not cls |
| 132 | and getattr(candidate, "default", True) |
| 133 | ) |
| 134 | ] |
| 135 | if len(app_configs) == 1: |
| 136 | app_config_class = app_configs[0][1] |
| 137 | else: |
| 138 | # Check if there's exactly one AppConfig subclass, |
| 139 | # among those that explicitly define default = True. |
| 140 | app_configs = [ |
| 141 | (name, candidate) |
| 142 | for name, candidate in app_configs |
| 143 | if getattr(candidate, "default", False) |
| 144 | ] |
| 145 | if len(app_configs) > 1: |
| 146 | candidates = [repr(name) for name, _ in app_configs] |
| 147 | raise RuntimeError( |
| 148 | "%r declares more than one default AppConfig: " |
| 149 | "%s." % (mod_path, ", ".join(candidates)) |
| 150 | ) |
| 151 | elif len(app_configs) == 1: |
| 152 | app_config_class = app_configs[0][1] |
| 153 | |
| 154 | # Use the default app config class if we didn't find anything. |
| 155 | if app_config_class is None: |
| 156 | app_config_class = cls |
| 157 | app_name = entry |
no test coverage detected