From d8ef4f1918f3108443a2dd3863e704f1ccebfe6e Mon Sep 17 00:00:00 2001 From: Nicolas Dandrimont Date: Tue, 30 Oct 2018 13:51:48 +0100 Subject: [PATCH] Refine the django.conf module check to see if the settings really are configured Some modules, e.g. hypothesis, load some Django modules for their own fixtures. This means that the `django.conf` module sometimes gets loaded, even though it's never used (and the settings are not initialized). This causes unrelated test failures when pytest_django is installed, as pytest_django considers that having a loaded django.conf means the settings are set up and ready to be modified. The Django settings object provides a flag to check this condition, which we now use. Add a regression test that mimics what hypothesis did which makes pytest-django fail. Closes #599. --- pytest_django/lazy_django.py | 22 +++++++++-------- tests/test_django_settings_module.py | 35 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/pytest_django/lazy_django.py b/pytest_django/lazy_django.py index b2d49bc70..9fd715bf9 100644 --- a/pytest_django/lazy_django.py +++ b/pytest_django/lazy_django.py @@ -15,16 +15,18 @@ def skip_if_no_django(): def django_settings_is_configured(): - # Avoid importing Django if it has not yet been imported - if ( - not os.environ.get("DJANGO_SETTINGS_MODULE") - and "django.conf" not in sys.modules - ): - return False - - # If DJANGO_SETTINGS_MODULE is defined at this point, Django is assumed to - # always be loaded. - return True + """Return whether the Django settings module has been configured. + + This uses either the DJANGO_SETTINGS_MODULE environment variable, or the + configured flag in the Django settings object if django.conf has already + been imported. + """ + ret = bool(os.environ.get("DJANGO_SETTINGS_MODULE")) + + if not ret and "django.conf" in sys.modules: + return sys.modules["django.conf"].settings.configured + + return ret def get_django_version(): diff --git a/tests/test_django_settings_module.py b/tests/test_django_settings_module.py index 3caff32cd..0e43442d3 100644 --- a/tests/test_django_settings_module.py +++ b/tests/test_django_settings_module.py @@ -406,6 +406,41 @@ def test_cfg(pytestconfig): assert r.ret == 0 +def test_no_ds_but_django_conf_imported(testdir, monkeypatch): + """pytest-django should not bail out, if "django.conf" has been imported + somewhere, e.g. via hypothesis (#599).""" + + monkeypatch.delenv('DJANGO_SETTINGS_MODULE') + + testdir.makepyfile(""" + import os + import sys + + # line copied from hypothesis/extras/django.py + from django.conf import settings as django_settings + + # Don't let pytest poke into this object, generating a + # django.core.exceptions.ImproperlyConfigured + del django_settings + + from pytest_django.lazy_django import django_settings_is_configured + + def test_django_settings_is_configured(): + assert django_settings_is_configured() is False + + def test_django_conf_is_imported(): + assert 'django.conf' in sys.modules + + def test_env(): + assert 'DJANGO_SETTINGS_MODULE' not in os.environ + + def test_cfg(pytestconfig): + assert pytestconfig.option.ds is None + """) + r = testdir.runpytest_subprocess('-s') + assert r.ret == 0 + + def test_no_django_settings_but_django_imported(testdir, monkeypatch): """Make sure we do not crash when Django happens to be imported, but settings is not properly configured"""