Skip to content

Commit 85581fb

Browse files
committed
Call django.setup() directly after configuring settings
1 parent 7f80222 commit 85581fb

File tree

4 files changed

+81
-36
lines changed

4 files changed

+81
-36
lines changed

pytest_django/compat.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,3 @@
2525

2626

2727
del _runner
28-
29-
30-
try:
31-
from django import setup
32-
except ImportError:
33-
# Emulate Django 1.7 django.setup() with get_models
34-
from django.db.models import get_models as setup

pytest_django/lazy_django.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,15 @@ def skip_if_no_django():
1414

1515

1616
def django_settings_is_configured():
17-
if not os.environ.get('DJANGO_SETTINGS_MODULE') \
18-
and not 'django' in sys.modules:
17+
# Avoid importing Django if it has not yet been imported
18+
if not os.environ.get('DJANGO_SETTINGS_MODULE') and 'django' not in sys.modules:
1919
return False
2020

21+
# If DJANGO_SETTINGS_MODULE is defined at this point, Django should always be loaded
2122
from django.conf import settings
22-
if settings.configured:
23-
return True
24-
25-
from django.core.exceptions import ImproperlyConfigured
26-
try:
27-
settings.DATABASES
28-
except (ImproperlyConfigured, ImportError):
29-
e = sys.exc_info()[1]
30-
raise pytest.UsageError(
31-
"pytest_django: failed to load Django settings: %s" % (e.args))
32-
33-
return settings.configured
23+
assert settings.configured is True
24+
return True
25+
3426

3527

3628
def get_django_version():

pytest_django/plugin.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
################ pytest hooks ################
2828

29-
3029
def pytest_addoption(parser):
3130
group = parser.getgroup('django')
3231
group._addoption('--reuse-db',
@@ -52,7 +51,7 @@ def pytest_addoption(parser):
5251
'Django settings module to use by pytest-django.')
5352

5453

55-
def _load_settings(config, options):
54+
def _load_settings_from_env(config, options):
5655
# Configure DJANGO_SETTINGS_MODULE
5756
ds = (options.ds or
5857
config.getini(SETTINGS_MODULE_ENV) or
@@ -73,12 +72,29 @@ def _load_settings(config, options):
7372
import configurations.importer
7473
configurations.importer.install()
7574

75+
# Forcefully load django settings, throws ImportError or ImproperlyConfigured
76+
# if settings cannot be loaded
77+
from django.conf import settings
78+
settings.DATABASES
79+
80+
_setup_django()
81+
82+
83+
def _setup_django():
84+
import django
85+
if hasattr(django, 'setup'):
86+
django.setup()
87+
else:
88+
# Emulate Django 1.7 django.setup() with get_models
89+
from django.db.models import get_models
90+
get_models()
7691

7792
if pytest.__version__[:3] >= "2.4":
7893
def pytest_load_initial_conftests(early_config, parser, args):
79-
_load_settings(early_config, parser.parse_known_args(args))
94+
_load_settings_from_env(early_config, parser.parse_known_args(args))
8095

8196

97+
@pytest.mark.trylast
8298
def pytest_configure(config):
8399
# Register the marks
84100
config.addinivalue_line(
@@ -95,10 +111,10 @@ def pytest_configure(config):
95111
'"my_app.test_urls".')
96112

97113
if pytest.__version__[:3] < "2.4":
98-
_load_settings(config, config.option)
99-
114+
_load_settings_from_env(config, config.option)
100115

101-
################ Autouse fixtures ################
116+
if django_settings_is_configured():
117+
_setup_django()
102118

103119

104120
@pytest.fixture(autouse=True, scope='session')
@@ -115,11 +131,8 @@ def _django_test_environment(request):
115131
"""
116132
if django_settings_is_configured():
117133
from django.conf import settings
118-
from .compat import (setup, setup_test_environment,
119-
teardown_test_environment)
134+
from .compat import setup_test_environment, teardown_test_environment
120135
settings.DEBUG = False
121-
setup()
122-
123136
setup_test_environment()
124137
request.addfinalizer(teardown_test_environment)
125138

tests/test_django_settings_module.py

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
If these tests fail you probably forgot to run "python setup.py develop".
44
"""
55

6+
import pytest
7+
import django
8+
69
BARE_SETTINGS = '''
710
# At least one database must be configured
811
DATABASES = {
@@ -76,11 +79,8 @@ def test_ds_non_existent(testdir, monkeypatch):
7679
monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'DOES_NOT_EXIST')
7780
testdir.makepyfile('def test_ds(): pass')
7881
result = testdir.runpytest()
79-
# NOTE: the error is on stdout, because it happens during the testrun.
80-
result.stdout.fnmatch_lines(
81-
["*ERROR at setup of test_ds*",
82-
"*UsageError: pytest_django: failed to load Django settings: "
83-
"Could not import settings 'DOES_NOT_EXIST' (Is it on sys.path?*): *"])
82+
result.stderr.fnmatch_lines(
83+
["*ImportError: Could not import settings 'DOES_NOT_EXIST' (Is it on sys.path?*): *"])
8484

8585

8686
def test_ds_after_user_conftest(testdir, monkeypatch):
@@ -214,5 +214,52 @@ def pytest_configure():
214214
def test_debug_is_false():
215215
assert settings.DEBUG is False
216216
""")
217+
217218
r = testdir.runpytest()
218219
assert r.ret == 0
220+
221+
222+
@pytest.mark.skipif(not hasattr(django, 'setup'),
223+
reason="This Django version does not support app loading")
224+
@pytest.mark.extra_settings("""
225+
INSTALLED_APPS = [
226+
'tpkg.app.apps.TestApp',
227+
]
228+
229+
""")
230+
def test_django_setup(django_testdir):
231+
django_testdir.create_app_file("""
232+
from django.apps import apps, AppConfig
233+
234+
from django.contrib.auth.models import AbstractUser
235+
from django.db import models
236+
237+
238+
class TestApp(AppConfig):
239+
name = 'tpkg.app'
240+
241+
def ready(self):
242+
print ('READY(): populating=%r' % apps._lock.locked())
243+
244+
""", 'apps.py')
245+
246+
django_testdir.create_app_file("""
247+
from django.apps import apps
248+
249+
print ('IMPORT: populating=%r,ready=%r' % (apps._lock.locked(), apps.ready))
250+
SOME_THING = 1234
251+
""", 'models.py')
252+
253+
django_testdir.create_app_file("", '__init__.py')
254+
django_testdir.makepyfile("""
255+
from django.apps import apps
256+
from tpkg.app.models import SOME_THING
257+
258+
def test_anything():
259+
print ('TEST: populating=%r,ready=%r' % (apps._lock.locked(), apps.ready))
260+
""")
261+
262+
result = django_testdir.runpytest('-s', '--tb=line')
263+
result.stdout.fnmatch_lines(['*IMPORT: populating=True,ready=False*'])
264+
result.stdout.fnmatch_lines(['*READY(): populating=True*'])
265+
result.stdout.fnmatch_lines(['*TEST: populating=False,ready=True*'])

0 commit comments

Comments
 (0)