From ebd78a9f97d8ba850d279a844d89a1d805370738 Mon Sep 17 00:00:00 2001 From: Iuri de Silvio Date: Mon, 10 Aug 2020 15:16:45 -0300 Subject: [PATCH] Fixed #31870 -- Fixed crash when populating app registry with empty or without apps module. Regression in 3f2821af6bc48fa8e7970c1ce27bc54c3172545e. --- django/apps/config.py | 16 +++--- .../__init__.py | 7 +++ .../apps.py | 0 .../__init__.py | 7 +++ tests/apps/tests.py | 52 +++++++++++++++++++ 5 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 tests/apps/explicit_default_config_empty_apps/__init__.py create mode 100644 tests/apps/explicit_default_config_empty_apps/apps.py create mode 100644 tests/apps/explicit_default_config_without_apps/__init__.py diff --git a/django/apps/config.py b/django/apps/config.py index 8c276d5d34..928e19ac44 100644 --- a/django/apps/config.py +++ b/django/apps/config.py @@ -89,6 +89,7 @@ class AppConfig: """ # create() eventually returns app_config_class(app_name, app_module). app_config_class = None + app_config_name = None app_name = None app_module = None @@ -161,12 +162,15 @@ class AppConfig: ) else: message += ( - "However, Django's automatic detection picked another " - "configuration, %r. You should move the default " - "config class to the apps submodule of your " - "application and, if this module defines several " - "config classes, mark the default one with default = " - "True." % app_config_name + "However, Django's automatic detection %s. You should " + "move the default config class to the apps submodule " + "of your application and, if this module defines " + "several config classes, mark the default one with " + "default = True." % ( + "picked another configuration, %r" % app_config_name + if app_config_name + else "did not find this configuration" + ) ) warnings.warn(message, RemovedInDjango41Warning, stacklevel=2) entry = new_entry diff --git a/tests/apps/explicit_default_config_empty_apps/__init__.py b/tests/apps/explicit_default_config_empty_apps/__init__.py new file mode 100644 index 0000000000..a7a4f548d7 --- /dev/null +++ b/tests/apps/explicit_default_config_empty_apps/__init__.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + +default_app_config = 'apps.explicit_default_config_empty_apps.ExplicitDefaultConfigEmptyApps' + + +class ExplicitDefaultConfigEmptyApps(AppConfig): + name = 'apps.explicit_default_config_empty_apps' diff --git a/tests/apps/explicit_default_config_empty_apps/apps.py b/tests/apps/explicit_default_config_empty_apps/apps.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/apps/explicit_default_config_without_apps/__init__.py b/tests/apps/explicit_default_config_without_apps/__init__.py new file mode 100644 index 0000000000..c42323376f --- /dev/null +++ b/tests/apps/explicit_default_config_without_apps/__init__.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + +default_app_config = 'apps.explicit_default_config_without_apps.ExplicitDefaultConfigWithoutApps' + + +class ExplicitDefaultConfigWithoutApps(AppConfig): + name = 'apps.explicit_default_config_without_apps' diff --git a/tests/apps/tests.py b/tests/apps/tests.py index f4b0a8879b..cf487a65da 100644 --- a/tests/apps/tests.py +++ b/tests/apps/tests.py @@ -10,9 +10,13 @@ from django.test.utils import extend_sys_path, isolate_apps from django.utils.deprecation import RemovedInDjango41Warning from .explicit_default_config_app.apps import ExplicitDefaultConfig +from .explicit_default_config_empty_apps import ExplicitDefaultConfigEmptyApps from .explicit_default_config_mismatch_app.not_apps import ( ExplicitDefaultConfigMismatch, ) +from .explicit_default_config_without_apps import ( + ExplicitDefaultConfigWithoutApps, +) from .models import SoAlternative, TotallyNormal, new_apps from .one_config_app.apps import OneConfig from .two_configs_one_default_app.apps import TwoConfig @@ -520,3 +524,51 @@ class DeprecationTests(SimpleTestCase): with self.settings(INSTALLED_APPS=['apps.explicit_default_config_mismatch_app']): config = apps.get_app_config('explicit_default_config_mismatch_app') self.assertIsInstance(config, ExplicitDefaultConfigMismatch) + + def test_explicit_default_app_config_empty_apps(self): + """ + Load an app that specifies a default AppConfig class in __init__ and + have an empty apps module. + """ + msg = ( + "'apps.explicit_default_config_empty_apps' defines " + "default_app_config = 'apps.explicit_default_config_empty_apps." + "ExplicitDefaultConfigEmptyApps'. However, Django's automatic " + "detection did not find this configuration. You should move the " + "default config class to the apps submodule of your application " + "and, if this module defines several config classes, mark the " + "default one with default = True." + ) + with self.assertRaisesMessage(RemovedInDjango41Warning, msg): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_empty_apps']): + pass + with ignore_warnings(category=RemovedInDjango41Warning): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_empty_apps']): + self.assertIsInstance( + apps.get_app_config('explicit_default_config_empty_apps'), + ExplicitDefaultConfigEmptyApps, + ) + + def test_explicit_default_app_config_without_apps(self): + """ + Load an app that specifies a default AppConfig class in __init__ and do + not have an apps module. + """ + msg = ( + "'apps.explicit_default_config_without_apps' defines " + "default_app_config = 'apps.explicit_default_config_without_apps." + "ExplicitDefaultConfigWithoutApps'. However, Django's automatic " + "detection did not find this configuration. You should move the " + "default config class to the apps submodule of your application " + "and, if this module defines several config classes, mark the " + "default one with default = True." + ) + with self.assertRaisesMessage(RemovedInDjango41Warning, msg): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_without_apps']): + pass + with ignore_warnings(category=RemovedInDjango41Warning): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_without_apps']): + self.assertIsInstance( + apps.get_app_config('explicit_default_config_without_apps'), + ExplicitDefaultConfigWithoutApps, + )