diff --git a/src/ptvsd/_vendored/pydevd/pydevd_plugins/django_debug.py b/src/ptvsd/_vendored/pydevd/pydevd_plugins/django_debug.py index 32ab05861..022a4668c 100644 --- a/src/ptvsd/_vendored/pydevd/pydevd_plugins/django_debug.py +++ b/src/ptvsd/_vendored/pydevd/pydevd_plugins/django_debug.py @@ -358,6 +358,17 @@ def _is_django_variable_does_not_exist_exception_break_context(frame): name = None return name in ('_resolve_lookup', 'find_template') + +def _is_ignoring_failures(frame): + while frame is not None: + if frame.f_code.co_name == 'resolve': + ignore_failures = frame.f_locals.get('ignore_failures') + if ignore_failures: + return True + frame = frame.f_back + + return False + #======================================================================================================================= # Django Step Commands #======================================================================================================================= @@ -520,15 +531,16 @@ def exception_break(plugin, main_debugger, pydb_frame, frame, args, arg): elif exception.__name__ == 'VariableDoesNotExist': if _is_django_variable_does_not_exist_exception_break_context(frame): - render_frame = _find_django_render_frame(frame) - if render_frame: - suspend_frame = suspend_django( - main_debugger, thread, DjangoTemplateFrame(render_frame), CMD_ADD_EXCEPTION_BREAK) - if suspend_frame: - add_exception_to_frame(suspend_frame, (exception, value, trace)) - thread.additional_info.pydev_message = 'VariableDoesNotExist' - suspend_frame.f_back = frame - frame = suspend_frame - return True, frame + if not getattr(exception, 'silent_variable_failure', False) and not _is_ignoring_failures(frame): + render_frame = _find_django_render_frame(frame) + if render_frame: + suspend_frame = suspend_django( + main_debugger, thread, DjangoTemplateFrame(render_frame), CMD_ADD_EXCEPTION_BREAK) + if suspend_frame: + add_exception_to_frame(suspend_frame, (exception, value, trace)) + thread.additional_info.pydev_message = 'VariableDoesNotExist' + suspend_frame.f_back = frame + frame = suspend_frame + return True, frame return None diff --git a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/templates/my_app/no_var_error.html b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/templates/my_app/no_var_error.html new file mode 100644 index 000000000..bdb84e562 --- /dev/null +++ b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/templates/my_app/no_var_error.html @@ -0,0 +1,5 @@ +{% if pat.name %} + pat.name={{ pat.name }} +{% else %} + no_pat_name +{% endif %} \ No newline at end of file diff --git a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/urls.py b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/urls.py index 209ade309..849aaf6b1 100644 --- a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/urls.py +++ b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/urls.py @@ -8,4 +8,5 @@ url(r'^template_error$', views.template_error, name='template_error'), url(r'^template_error2$', views.template_error2, name='template_error2'), url(r'^inherits$', views.inherits, name='inherits'), + url(r'^no_var_error$', views.no_var_error, name='no_var_error'), ] diff --git a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/views.py b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/views.py index fbf527a12..c15a9946e 100644 --- a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/views.py +++ b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_17/my_app/views.py @@ -65,3 +65,9 @@ def template_error2(request): context = {} ret = render(request, 'my_app/template_error2.html', context) return ret + + +def no_var_error(request): + context = {} + ret = render(request, 'my_app/no_var_error.html', context) + return ret diff --git a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/templates/my_app/no_var_error.html b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/templates/my_app/no_var_error.html new file mode 100644 index 000000000..bdb84e562 --- /dev/null +++ b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/templates/my_app/no_var_error.html @@ -0,0 +1,5 @@ +{% if pat.name %} + pat.name={{ pat.name }} +{% else %} + no_pat_name +{% endif %} \ No newline at end of file diff --git a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/urls.py b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/urls.py index d16734af3..ada7ec44b 100644 --- a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/urls.py +++ b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/urls.py @@ -8,4 +8,5 @@ url(r'^template_error2$', views.template_error2, name='template_error2'), url(r'^template_error$', views.template_error, name='template_error'), url(r'^inherits$', views.inherits, name='inherits'), + url(r'^no_var_error$', views.no_var_error, name='no_var_error'), ] diff --git a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/views.py b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/views.py index 19289a60a..db7872d4b 100644 --- a/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/views.py +++ b/src/ptvsd/_vendored/pydevd/tests_python/my_django_proj_21/my_app/views.py @@ -72,3 +72,9 @@ def inherits(request): context = {} ret = render(request, 'my_app/inherits.html', context) return ret + + +def no_var_error(request): + context = {} + ret = render(request, 'my_app/no_var_error.html', context) + return ret diff --git a/src/ptvsd/_vendored/pydevd/tests_python/test_debugger.py b/src/ptvsd/_vendored/pydevd/tests_python/test_debugger.py index b45d0a18d..ad71b55bc 100644 --- a/src/ptvsd/_vendored/pydevd/tests_python/test_debugger.py +++ b/src/ptvsd/_vendored/pydevd/tests_python/test_debugger.py @@ -963,6 +963,26 @@ def test_case_django_template_inherits_no_exception(case_setup_django): writer.finished_ok = True +@pytest.mark.skipif(not TEST_DJANGO, reason='No django available') +def test_case_django_no_var_error(case_setup_django): + with case_setup_django.test_file(EXPECTED_RETURNCODE='any') as writer: + + # Check that it doesn't have issues with inherits + django exception breakpoints. + writer.write_add_exception_breakpoint_django() + + writer.write_make_initial_run() + + t = writer.create_request_thread('my_app/no_var_error') + time.sleep(5) # Give django some time to get to startup before requesting the page + t.start() + contents = t.wait_for_contents() + + contents = contents.replace(' ', '').replace('\r', '').replace('\n', '') + assert contents == '''no_pat_name''' + + writer.finished_ok = True + + @pytest.mark.skipif(not TEST_DJANGO, reason='No django available') @pytest.mark.parametrize("jmc", [False, True]) def test_case_django_no_attribute_exception_breakpoint(case_setup_django, jmc):