diff --git a/HISTORY.rst b/HISTORY.rst index 3fd0cf6..b91b7de 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,6 +2,11 @@ History ======= +* Make ``FIRST_PARTY_APPS`` handling match the behaviour of ``INSTALLED_APPS``. + + Thanks to Martin Bächtold for the report in `Pull Request #62 + `__. + * Stop distributing tests to reduce package size. Tests are not intended to be run outside of the tox setup in the repository. Repackagers can use GitHub's tarballs per tag. diff --git a/src/django_linear_migrations/apps.py b/src/django_linear_migrations/apps.py index e7f3759..781d33c 100644 --- a/src/django_linear_migrations/apps.py +++ b/src/django_linear_migrations/apps.py @@ -1,11 +1,14 @@ import pkgutil +from functools import lru_cache from importlib import import_module, reload from pathlib import Path from django.apps import AppConfig, apps from django.conf import settings from django.core.checks import Error, Tags, register +from django.core.signals import setting_changed from django.db.migrations.loader import MigrationLoader +from django.dispatch import receiver from django.utils.functional import cached_property from django_linear_migrations.compat import is_namespace_module @@ -19,9 +22,23 @@ def ready(self): register(Tags.models)(check_max_migration_files) +@lru_cache(maxsize=1) +def get_first_party_app_labels(): + if not settings.is_overridden("FIRST_PARTY_APPS"): + return None + return {AppConfig.create(name).label for name in settings.FIRST_PARTY_APPS} + + +@receiver(setting_changed) +def reset_first_party_app_labels(*, setting, **kwargs): + if setting == "FIRST_PARTY_APPS": + get_first_party_app_labels.cache_clear() + + def is_first_party_app_config(app_config): - if settings.is_overridden("FIRST_PARTY_APPS"): - return app_config.label in settings.FIRST_PARTY_APPS + first_party_labels = get_first_party_app_labels() + if first_party_labels is not None: + return app_config.label in first_party_labels # Check if it seems to be installed in a virtualenv path = Path(app_config.path) diff --git a/tests/test_apps.py b/tests/test_apps.py new file mode 100644 index 0000000..011ab7b --- /dev/null +++ b/tests/test_apps.py @@ -0,0 +1,31 @@ +from django.apps import apps +from django.test import SimpleTestCase +from django.test.utils import override_settings + +from django_linear_migrations.apps import is_first_party_app_config + + +class IsFirstPartyAppConfigTests(SimpleTestCase): + @override_settings(FIRST_PARTY_APPS=[]) + def test_empty(self): + app_config = apps.get_app_config("testapp") + + assert not is_first_party_app_config(app_config) + + @override_settings(FIRST_PARTY_APPS=["django_linear_migrations"]) + def test_not_named(self): + app_config = apps.get_app_config("testapp") + + assert not is_first_party_app_config(app_config) + + @override_settings(FIRST_PARTY_APPS=["tests.testapp"]) + def test_named_by_path(self): + app_config = apps.get_app_config("testapp") + + assert is_first_party_app_config(app_config) + + @override_settings(FIRST_PARTY_APPS=["tests.testapp.apps.TestAppConfig"]) + def test_named_by_app_config_path(self): + app_config = apps.get_app_config("testapp") + + assert is_first_party_app_config(app_config) diff --git a/tests/testapp/__init__.py b/tests/testapp/__init__.py index e69de29..c88ef64 100644 --- a/tests/testapp/__init__.py +++ b/tests/testapp/__init__.py @@ -0,0 +1,4 @@ +import django + +if django.VERSION < (3, 2): + default_app_config = "tests.testapp.apps.TestAppConfig" diff --git a/tests/testapp/apps.py b/tests/testapp/apps.py new file mode 100644 index 0000000..9c1f9a7 --- /dev/null +++ b/tests/testapp/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TestAppConfig(AppConfig): + name = "tests.testapp" + verbose_name = "Test App"