Skip to content

Commit 72d4f5b

Browse files
committed
remove cache, use session-scoped fixture
1 parent 3212cc2 commit 72d4f5b

File tree

3 files changed

+66
-41
lines changed

3 files changed

+66
-41
lines changed

pytest_django/lazy_django.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
import pytest
99

1010

11-
_django_settings_is_configured = None
12-
13-
1411
def skip_if_no_django():
1512
"""Raises a skip exception when no Django settings are available"""
1613
if not django_settings_is_configured():
@@ -24,17 +21,12 @@ def django_settings_is_configured():
2421
configured flag in the Django settings object if django.conf has already
2522
been imported.
2623
"""
27-
global _django_settings_is_configured
28-
29-
if _django_settings_is_configured is None:
30-
ret = bool(os.environ.get("DJANGO_SETTINGS_MODULE"))
31-
32-
if not ret and "django.conf" in sys.modules:
33-
ret = sys.modules["django.conf"].settings.configured
24+
ret = bool(os.environ.get("DJANGO_SETTINGS_MODULE"))
3425

35-
_django_settings_is_configured = ret
26+
if not ret and "django.conf" in sys.modules:
27+
ret = sys.modules["django.conf"].settings.configured
3628

37-
return _django_settings_is_configured
29+
return ret
3830

3931

4032
def get_django_version():

pytest_django/plugin.py

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,13 @@ def get_order_number(test):
451451
items[:] = sorted(items, key=get_order_number)
452452

453453

454+
@pytest.fixture(scope="session")
455+
def _django_settings_is_configured():
456+
return django_settings_is_configured()
457+
458+
454459
@pytest.fixture(autouse=True, scope="session")
455-
def django_test_environment(request):
460+
def django_test_environment(_django_settings_is_configured):
456461
"""
457462
Ensure that Django is loaded and has its testing environment setup.
458463
@@ -463,18 +468,22 @@ def django_test_environment(request):
463468
without duplicating a lot more of Django's test support code
464469
we need to follow this model.
465470
"""
466-
if django_settings_is_configured():
471+
if _django_settings_is_configured:
467472
_setup_django()
468473
from django.conf import settings as dj_settings
469474
from django.test.utils import setup_test_environment, teardown_test_environment
470475

471476
dj_settings.DEBUG = False
472477
setup_test_environment()
473-
request.addfinalizer(teardown_test_environment)
478+
479+
yield
480+
481+
if _django_settings_is_configured:
482+
teardown_test_environment()
474483

475484

476485
@pytest.fixture(scope="session")
477-
def django_db_blocker():
486+
def django_db_blocker(_django_settings_is_configured):
478487
"""Wrapper around Django's database access.
479488
480489
This object can be used to re-enable database access. This fixture is used
@@ -487,10 +496,8 @@ def django_db_blocker():
487496
This is an advanced feature that is meant to be used to implement database
488497
fixtures.
489498
"""
490-
if not django_settings_is_configured():
491-
return None
492-
493-
return _blocking_manager
499+
if _django_settings_is_configured:
500+
return _blocking_manager
494501

495502

496503
@pytest.fixture(autouse=True)
@@ -512,9 +519,9 @@ def _django_db_marker(request):
512519

513520

514521
@pytest.fixture(autouse=True, scope="class")
515-
def _django_setup_unittest(request, django_db_blocker):
522+
def _django_setup_unittest(request, django_db_blocker, _django_settings_is_configured):
516523
"""Setup a django unittest, internal to pytest-django."""
517-
if not django_settings_is_configured() or not is_django_unittest(request):
524+
if not _django_settings_is_configured or not is_django_unittest(request):
518525
yield
519526
return
520527

@@ -553,23 +560,20 @@ def _cleaning_debug(self):
553560

554561

555562
@pytest.fixture(scope="function", autouse=True)
556-
def _dj_autoclear_mailbox():
557-
if not django_settings_is_configured():
558-
return
559-
560-
from django.core import mail
563+
def _dj_autoclear_mailbox(_django_settings_is_configured):
564+
if _django_settings_is_configured:
565+
from django.core import mail
561566

562-
del mail.outbox[:]
567+
del mail.outbox[:]
563568

564569

565570
@pytest.fixture(scope="function")
566-
def mailoutbox(monkeypatch, django_mail_patch_dns, _dj_autoclear_mailbox):
567-
if not django_settings_is_configured():
568-
return
571+
def mailoutbox(monkeypatch, django_mail_patch_dns, _dj_autoclear_mailbox,
572+
_django_settings_is_configured):
573+
if _django_settings_is_configured:
574+
from django.core import mail
569575

570-
from django.core import mail
571-
572-
return mail.outbox
576+
return mail.outbox
573577

574578

575579
@pytest.fixture(scope="function")
@@ -615,7 +619,7 @@ def restore():
615619

616620

617621
@pytest.fixture(autouse=True, scope="session")
618-
def _fail_for_invalid_template_variable(request):
622+
def _fail_for_invalid_template_variable(_django_settings_is_configured):
619623
"""Fixture that fails for invalid variables in templates.
620624
621625
This fixture will fail each test that uses django template rendering
@@ -687,7 +691,7 @@ def __mod__(self, var):
687691

688692
if (
689693
os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true"
690-
and django_settings_is_configured()
694+
and _django_settings_is_configured
691695
):
692696
from django.conf import settings as dj_settings
693697

@@ -700,12 +704,12 @@ def __mod__(self, var):
700704

701705

702706
@pytest.fixture(autouse=True)
703-
def _template_string_if_invalid_marker(request):
707+
def _template_string_if_invalid_marker(request, _django_settings_is_configured):
704708
"""Apply the @pytest.mark.ignore_template_errors marker,
705709
internal to pytest-django."""
706710
marker = request.keywords.get("ignore_template_errors", None)
707711
if os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true":
708-
if marker and django_settings_is_configured():
712+
if marker and _django_settings_is_configured:
709713
from django.conf import settings as dj_settings
710714

711715
if dj_settings.TEMPLATES:
@@ -715,12 +719,11 @@ def _template_string_if_invalid_marker(request):
715719

716720

717721
@pytest.fixture(autouse=True, scope="function")
718-
def _django_clear_site_cache():
722+
def _django_clear_site_cache(_django_settings_is_configured):
719723
"""Clears ``django.contrib.sites.models.SITE_CACHE`` to avoid
720724
unexpected behavior with cached site objects.
721725
"""
722-
723-
if django_settings_is_configured():
726+
if _django_settings_is_configured:
724727
from django.conf import settings as dj_settings
725728

726729
if "django.contrib.sites" in dj_settings.INSTALLED_APPS:

tests/test_django_settings_module.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,33 @@ def test_no_django_settings_but_django_imported(testdir, monkeypatch):
450450
testdir.makeconftest("import django")
451451
r = testdir.runpytest_subprocess("--help")
452452
assert r.ret == 0
453+
454+
455+
def test_django_settings_is_configured_cached(testdir, monkeypatch):
456+
"""
457+
``django_settings_is_configured`` should return the initial value always.
458+
459+
This avoids having the _dj_autoclear_mailbox autouse fixture trigger
460+
"AttributeError: module 'django.core.mail' has no attribute 'outbox'".
461+
"""
462+
monkeypatch.delenv("DJANGO_SETTINGS_MODULE")
463+
464+
p = testdir.makepyfile(
465+
"""
466+
from pytest_django.lazy_django import django_settings_is_configured
467+
468+
def test_1(_django_settings_is_configured):
469+
import os
470+
471+
assert not _django_settings_is_configured
472+
assert not django_settings_is_configured()
473+
474+
os.environ["DJANGO_SETTINGS_MODULE"] = "ignored_dsm"
475+
476+
def test_2(_django_settings_is_configured):
477+
assert not _django_settings_is_configured
478+
assert django_settings_is_configured()
479+
""")
480+
result = testdir.runpytest_subprocess(p, "-s")
481+
result.stdout.fnmatch_lines(["*2 passed in*"])
482+
assert result.ret == 0

0 commit comments

Comments
 (0)