Race-condition caused by when constance registers Django checks
caioariede opened this issue · 2 comments
Describe the problem
Using django-constance with pytest causes race-condition in settings load because of a misplaced import:
Django documentation recommends in [link]:
Lastly, your check function must be registered explicitly with system check registry. Checks should be registered in a file that’s loaded when your application is loaded; for example, in the AppConfig.ready() method.
This is how the race-condition happens:
- Pytest plugin manager loads the
constance/test/pytest.py
file - The
constance/test/pytest.py
file refers toconstance/__init__.py
in:
- The
constance/__init__.py
causes checks to be registered in:
- Important: This happens before pytest-django can set up Django here
- Whenever checks are loaded, it will cascade-load Django checks as well
- Django checks will try to load internal stuff like caches and database
- Whenever Django detects cache/database isn't configured, it will configure them before knowing what the final state of settings would be
- Pytest plugin manager will now trigger all the hooks for plugins to load correctly (eg.
pytest_configure
) - The pytest-django plugin finally sets settings up - this is when constance should register its checks
- Important: Now if you compare
django.conf.settings
withdjango.db.connections.settings
they can likely be different as below:
(Pdb) from django.conf import settings
(Pdb) p settings
<dynaconf.base.LazySettings object at 0x1127de640>
(Pdb) p settings.DATABASES
<Box: {'default': {'NAME': 'local', 'USER': '', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': '', 'CONN_MAX_AGE': 500, 'ENGINE': 'django.db.backends.postgresql_psycopg2'}}>
(Pdb) from django.db import connections
(Pdb) p connections
<django.db.utils.ConnectionHandler object at 0x111fa4c40>
(Pdb) p connections.settings
{'default': {'ENGINE': 'django.db.backends.dummy', 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'OPTIONS': {}, 'TIME_ZONE': None, 'NAME': '', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', 'TEST': {'CHARSET': None, 'COLLATION': None, 'MIGRATE': True, 'MIRROR': None, 'NAME': None}}}
Steps to reproduce
I think this really depends on your set up. I was able to reproduce it using dynaconf probably because of the way it overrides Django settings. Nonetheless, I'm sure that if constance can load checks correctly this shouldn't be a problem.
System configuration
- Django version: 3.2
- Python version: 3.9
- Django-Constance version: 2.7
@caioariede please try with the latest master if the issue was resolved.
@camilonova I'm not able to test this now but I've reviewed the PR and from the looks of it, this issue should be granted as solved. Thanks!