From 787ceef5dd5a452290e8bf29216d8866b9a9ccca Mon Sep 17 00:00:00 2001 From: Xavier Fernandez Date: Tue, 24 Oct 2023 17:50:55 +0200 Subject: [PATCH 1/3] Make sure InvalidVarException.fail is reset after a test using ignore_template_errors marker --- pytest_django/plugin.py | 8 ++++++-- tests/test_environment.py | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 032fe9e0..7dcef972 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -639,7 +639,7 @@ def __mod__(self, var: str) -> str: @pytest.fixture(autouse=True) -def _template_string_if_invalid_marker(request) -> None: +def _template_string_if_invalid_marker(monkeypatch, request) -> None: """Apply the @pytest.mark.ignore_template_errors marker, internal to pytest-django.""" marker = request.keywords.get("ignore_template_errors", None) @@ -648,7 +648,11 @@ def _template_string_if_invalid_marker(request) -> None: from django.conf import settings as dj_settings if dj_settings.TEMPLATES: - dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"].fail = False + monkeypatch.setattr( + dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"], + "fail", + False, + ) @pytest.fixture(autouse=True, scope="function") diff --git a/tests/test_environment.py b/tests/test_environment.py index 782d093a..6b55aa8b 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -101,6 +101,47 @@ def test_ignore(client): ) +@pytest.mark.django_project( + extra_settings=""" + TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + ) + """ +) +def test_invalid_template_variable_marker_cleanup(django_testdir) -> None: + django_testdir.create_app_file( + "
{{ invalid_var }}
", "templates/invalid_template_base.html" + ) + django_testdir.create_app_file( + "{% include 'invalid_template_base.html' %}", "templates/invalid_template.html" + ) + django_testdir.create_test_module( + """ + from django.template.loader import render_to_string + + import pytest + + @pytest.mark.ignore_template_errors + def test_ignore(client): + render_to_string('invalid_template.html') + + def test_for_invalid_template(client): + render_to_string('invalid_template.html') + + """ + ) + result = django_testdir.runpytest_subprocess("-s", "--fail-on-template-vars") + + origin = "'*/tpkg/app/templates/invalid_template_base.html'" + result.stdout.fnmatch_lines_random( + [ + "tpkg/test_the_test.py .F*", + f"E * Failed: Undefined template variable 'invalid_var' in {origin}", + ] + ) + + @pytest.mark.django_project( extra_settings=""" TEMPLATE_LOADERS = ( From 86a93e7ba4af547b9a8950c4458a2467da4302db Mon Sep 17 00:00:00 2001 From: Xavier Fernandez Date: Thu, 26 Oct 2023 10:18:33 +0200 Subject: [PATCH 2/3] Add cleanup to _fail_for_invalid_template_variable fixture --- pytest_django/plugin.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 7dcef972..36907a58 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -628,14 +628,20 @@ def __mod__(self, var: str) -> str: else: return msg - if ( - os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true" - and django_settings_is_configured() - ): - from django.conf import settings as dj_settings + with pytest.MonkeyPatch.context() as mp: + if ( + os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true" + and django_settings_is_configured() + ): + from django.conf import settings as dj_settings - if dj_settings.TEMPLATES: - dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"] = InvalidVarException() + if dj_settings.TEMPLATES: + mp.setitem( + dj_settings.TEMPLATES[0]["OPTIONS"], + "string_if_invalid", + InvalidVarException(), + ) + yield @pytest.fixture(autouse=True) From e9db1b74d6b817de3cb2159ca67a3f4c68dd6421 Mon Sep 17 00:00:00 2001 From: Xavier Fernandez Date: Thu, 26 Oct 2023 10:43:11 +0200 Subject: [PATCH 3/3] Adapt patch for pytest < 6.2 --- pytest_django/plugin.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 36907a58..a79cd7d0 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -628,20 +628,26 @@ def __mod__(self, var: str) -> str: else: return msg - with pytest.MonkeyPatch.context() as mp: - if ( - os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true" - and django_settings_is_configured() - ): - from django.conf import settings as dj_settings + # TODO: use pytest.MonkeyPatch once pytest<6.2 is not supported anymore + NOT_SET = object() + changed = False + previous_value = NOT_SET + if ( + os.environ.get(INVALID_TEMPLATE_VARS_ENV, "false") == "true" + and django_settings_is_configured() + ): + from django.conf import settings as dj_settings - if dj_settings.TEMPLATES: - mp.setitem( - dj_settings.TEMPLATES[0]["OPTIONS"], - "string_if_invalid", - InvalidVarException(), - ) - yield + if dj_settings.TEMPLATES: + previous_value = dj_settings.TEMPLATES[0]["OPTIONS"].get("string_if_invalid", NOT_SET) + dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"] = InvalidVarException() + changed = True + yield + if changed: + if previous_value is NOT_SET: + del dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"] + else: + dj_settings.TEMPLATES[0]["OPTIONS"]["string_if_invalid"] = previous_value @pytest.fixture(autouse=True)