#33013: "AppConfig" subclass imports found in Django 3.2's automatic "AppConfig" discovery ----------------------------------------+------------------------ Reporter: jwayodi | Owner: nobody Type: Bug | Status: new Component: Core (Other) | Version: 3.2 Severity: Normal | Keywords: Triage Stage: Unreviewed | Has patch: 0 Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | ----------------------------------------+------------------------ We are in the process of adding support for Django 3.2 to [https://github.com/django-oscar/django-oscar Oscar].
Oscar [https://github.com/django-oscar/django- oscar/blob/04dd391c900537a61dbb0ae5250ca5c2df6bbc4b/src/oscar/core/application.py#L139 mixes in] its apps' configurations into Django's `AppConfig` class, and developers using Oscar then subclass these, to make their own modifications: {{{ # my_app/apps.py from oscar.core.application import OscarConfig class MyAppConfig(OscarConfig): # my app modifications }}} With Django 3.2, for apps added to `INSTALLED_APPS` using the dotted Python path to the app package, Django finds all `AppConfig` subclasses in the `apps.py` (using [https://github.com/django/django/commit/3f2821af6bc48fa8e7970c1ce27bc54c3172545e #diff- 0f8bc657bc27c9f80385c4814c2c2ebc033bda3e03285a7212965309a481cc70R110-R120 Python's] `inspect.getmembers`), including ones imported to be subclassed. `django.apps.config.AppConfig` itself does get excluded, but this is not sufficient, as we and the developers using Oscar do a lot of sub classing of these classes. To solve this, we would have have to do: {{{ # my_app/apps.py from oscar.core import application class MyAppConfig(application.OscarConfig): # my app modifications }}} And then ask the developers using Oscar to also do the same. The problem with this is: - it is not intuitive - Python developers would not typically expect imports to cause side effects like this, which creates the potential for confusing and hard-to-debug issues - it is flaky - a new developer may innocently refactor imports not realising why they were done that way, and then encounter the confusing issues - explicit class imports are normally preferred in Python, unless they cause local name clashes, so requiring them for this reason is a bit odd - Django itself [https://github.com/django/django/commit/3f2821af6bc48fa8e7970c1ce27bc54c3172545e #diff- 0f8bc657bc27c9f80385c4814c2c2ebc033bda3e03285a7212965309a481cc70R110-R120 does a check] to exclude `django.apps.config.AppConfig` from being detected, which is indicative of the fundamental issue which remains It would be nice if Django could mitigate this by having a mechanism for deciding which classes are considered (e.g. using something like the `abstract` metadata option used for models). In the short term, restricting the scanning for `AppConfig` subclasses to those named in the `app.py`'s `__all__` variable, if it has one (by e.g. [https://github.com/django/django/commit/3f2821af6bc48fa8e7970c1ce27bc54c3172545e #diff- 0f8bc657bc27c9f80385c4814c2c2ebc033bda3e03285a7212965309a481cc70R110-R120 adding the filter] `(not hasattr(mod, "__all__") or candidate.__name__ in mod.__all__)`), would work, and is a bit more intuitive. -- Ticket URL: <https://code.djangoproject.com/ticket/33013> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/050.495b7bf4403fd0579ea5ed412f63e575%40djangoproject.com.