#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.

Reply via email to