Refs #31180 -- Removed default_app_config application configuration variable per deprecation timeline.

This commit is contained in:
Mariusz Felisiak 2021-09-16 09:06:40 +02:00
parent d25710a625
commit 75d6c4ae6d
11 changed files with 7 additions and 184 deletions

View File

@ -1,10 +1,8 @@
import inspect
import os
import warnings
from importlib import import_module
from django.core.exceptions import ImproperlyConfigured
from django.utils.deprecation import RemovedInDjango41Warning
from django.utils.functional import cached_property
from django.utils.module_loading import import_string, module_has_submodule
@ -102,7 +100,6 @@ 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
@ -134,7 +131,6 @@ class AppConfig:
]
if len(app_configs) == 1:
app_config_class = app_configs[0][1]
app_config_name = '%s.%s' % (mod_path, app_configs[0][0])
else:
# Check if there's exactly one AppConfig subclass,
# among those that explicitly define default = True.
@ -151,43 +147,11 @@ class AppConfig:
)
elif len(app_configs) == 1:
app_config_class = app_configs[0][1]
app_config_name = '%s.%s' % (mod_path, app_configs[0][0])
# If app_module specifies a default_app_config, follow the link.
# default_app_config is deprecated, but still takes over the
# automatic detection for backwards compatibility during the
# deprecation period.
try:
new_entry = app_module.default_app_config
except AttributeError:
# Use the default app config class if we didn't find anything.
if app_config_class is None:
app_config_class = cls
app_name = entry
else:
message = (
'%r defines default_app_config = %r. ' % (entry, new_entry)
)
if new_entry == app_config_name:
message += (
'Django now detects this configuration automatically. '
'You can remove default_app_config.'
)
else:
message += (
"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
app_config_class = None
# Use the default app config class if we didn't find anything.
if app_config_class is None:
app_config_class = cls
app_name = entry
# If import_string succeeds, entry is an app config class.
if app_config_class is None:

View File

@ -255,3 +255,5 @@ to remove usage of these features.
* The ``whitelist`` argument and ``domain_whitelist`` attribute of
``django.core.validators.EmailValidator`` are removed.
* The ``default_app_config`` application configuration variable is removed.

View File

@ -1 +0,0 @@
default_app_config = 'apps.explicit_default_config_app.apps.ExplicitDefaultConfig'

View File

@ -1,5 +0,0 @@
from django.apps import AppConfig
class ExplicitDefaultConfig(AppConfig):
name = 'apps.explicit_default_config_app'

View File

@ -1,7 +0,0 @@
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'

View File

@ -1 +0,0 @@
default_app_config = 'apps.explicit_default_config_mismatch_app.not_apps.ExplicitDefaultConfigMismatch'

View File

@ -1,5 +0,0 @@
from django.apps import AppConfig
class ImplicitDefaultConfigMismatch(AppConfig):
name = 'apps.explicit_default_config_mismatch_app'

View File

@ -1,5 +0,0 @@
from django.apps import AppConfig
class ExplicitDefaultConfigMismatch(AppConfig):
name = 'apps.explicit_default_config_mismatch_app'

View File

@ -1,7 +0,0 @@
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'

View File

@ -5,18 +5,9 @@ from django.apps.registry import Apps
from django.contrib.admin.models import LogEntry
from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
from django.db import models
from django.test import SimpleTestCase, ignore_warnings, override_settings
from django.test import SimpleTestCase, override_settings
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
@ -511,106 +502,3 @@ class NamespacePackageAppTests(SimpleTestCase):
with self.settings(INSTALLED_APPS=['nsapp.apps.NSAppConfig']):
app_config = apps.get_app_config('nsapp')
self.assertEqual(app_config.path, self.app_path)
class DeprecationTests(SimpleTestCase):
@ignore_warnings(category=RemovedInDjango41Warning)
def test_explicit_default_app_config(self):
with self.settings(INSTALLED_APPS=['apps.explicit_default_config_app']):
config = apps.get_app_config('explicit_default_config_app')
self.assertIsInstance(config, ExplicitDefaultConfig)
def test_explicit_default_app_config_warning(self):
"""
Load an app that specifies a default AppConfig class matching the
autodetected one.
"""
msg = (
"'apps.explicit_default_config_app' defines default_app_config = "
"'apps.explicit_default_config_app.apps.ExplicitDefaultConfig'. "
"Django now detects this configuration automatically. You can "
"remove default_app_config."
)
with self.assertRaisesMessage(RemovedInDjango41Warning, msg):
with self.settings(INSTALLED_APPS=['apps.explicit_default_config_app']):
pass
with ignore_warnings(category=RemovedInDjango41Warning):
with self.settings(INSTALLED_APPS=['apps.explicit_default_config_app']):
self.assertIsInstance(
apps.get_app_config('explicit_default_config_app'),
ExplicitDefaultConfig,
)
def test_explicit_default_app_config_mismatch(self):
"""
Load an app that specifies a default AppConfig class not matching the
autodetected one.
"""
msg = (
"'apps.explicit_default_config_mismatch_app' defines "
"default_app_config = 'apps.explicit_default_config_mismatch_app."
"not_apps.ExplicitDefaultConfigMismatch'. However, Django's "
"automatic detection picked another configuration, 'apps."
"explicit_default_config_mismatch_app.apps."
"ImplicitDefaultConfigMismatch'. 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_mismatch_app']):
pass
with ignore_warnings(category=RemovedInDjango41Warning):
with self.settings(INSTALLED_APPS=['apps.explicit_default_config_mismatch_app']):
self.assertIsInstance(
apps.get_app_config('explicit_default_config_mismatch_app'),
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,
)