Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Django 2.2 tests and fixes for exception breakpoints in Django 1.7. Fixes #1298, #1294 #1310

Merged
merged 2 commits into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/ptvsd/_vendored/pydevd/.travis_install_python_deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ fi

if [ "$PYDEVD_PYTHON_VERSION" = "3.6" ]; then
conda install --yes pyqt=5 gevent
pip install "django>=2.1,<2.2"
pip install "django>=2.2,<2.3"
fi

if [ "$PYDEVD_PYTHON_VERSION" = "3.7" ]; then
conda install --yes pyqt=5 matplotlib
# Note: track the latest django
pip install "django>=2.1,<2.2"
pip install "django"
fi

pip install untangle
Expand Down
67 changes: 48 additions & 19 deletions src/ptvsd/_vendored/pydevd/pydevd_plugins/django_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
#=======================================================================================================================
Expand Down Expand Up @@ -466,6 +477,21 @@ def suspend(plugin, main_debugger, thread, frame, bp_type):
return None


def _get_filename_from_origin_in_parent_frame_locals(frame, parent_frame_name):
filename = None
parent_frame = frame
while parent_frame.f_code.co_name != parent_frame_name:
parent_frame = parent_frame.f_back

origin = None
if parent_frame is not None:
origin = parent_frame.f_locals.get('origin')

if hasattr(origin, 'name') and origin.name is not None:
filename = normcase(_convert_to_str(origin.name))
return filename


def exception_break(plugin, main_debugger, pydb_frame, frame, args, arg):
main_debugger = args[0]
thread = args[3]
Expand All @@ -479,19 +505,21 @@ def exception_break(plugin, main_debugger, pydb_frame, frame, args, arg):
# In this case we don't actually have a regular render frame with the context
# (we didn't really get to that point).
token = getattr(value, 'token', None)

if token is None:
# Django 1.7 does not have token in exception. Try to get it from locals.
token = frame.f_locals.get('token')

lineno = getattr(token, 'lineno', None)

filename = None
if lineno is not None:
get_template_frame = frame
while get_template_frame.f_code.co_name != 'get_template':
get_template_frame = get_template_frame.f_back

origin = None
if get_template_frame is not None:
origin = get_template_frame.f_locals.get('origin')
filename = _get_filename_from_origin_in_parent_frame_locals(frame, 'get_template')

if hasattr(origin, 'name') and origin.name is not None:
filename = normcase(_convert_to_str(origin.name))
if filename is None:
# Django 1.7 does not have origin in get_template. Try to get it from
# load_template.
filename = _get_filename_from_origin_in_parent_frame_locals(frame, 'load_template')

if filename is not None and lineno is not None:
syntax_error_frame = DjangoTemplateSyntaxErrorFrame(
Expand All @@ -503,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
23 changes: 21 additions & 2 deletions src/ptvsd/_vendored/pydevd/tests_python/debugger_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
CMD_ADD_EXCEPTION_BREAK

import sys
import time


def get_java_location():
Expand Down Expand Up @@ -134,6 +135,15 @@ def create_request_thread(self, url=''):

class T(threading.Thread):

def wait_for_contents(self):
for _ in range(10):
if hasattr(self, 'contents'):
break
time.sleep(.3)
else:
raise AssertionError('Django did not return contents properly!')
return self.contents

def run(self):
try:
from urllib.request import urlopen
Expand Down Expand Up @@ -203,6 +213,15 @@ def create_request_thread(self, uri):

class T(threading.Thread):

def wait_for_contents(self):
for _ in range(10):
if hasattr(self, 'contents'):
break
time.sleep(.3)
else:
raise AssertionError('Django did not return contents properly!')
return self.contents

def run(self):
try:
from urllib.request import urlopen
Expand Down Expand Up @@ -442,10 +461,10 @@ def test_file(self, **kwargs):
version = [int(x) for x in django.get_version().split('.')][:2]
if version == [1, 7]:
django_folder = 'my_django_proj_17'
elif version == [2, 1]:
elif version in ([2, 1], [2, 2]):
django_folder = 'my_django_proj_21'
else:
raise AssertionError('Can only check django 1.7 and 2.1 right now. Found: %s' % (version,))
raise AssertionError('Can only check django 1.7, 2.1 and 2.2 right now. Found: %s' % (version,))

WriterThread.DJANGO_FOLDER = django_folder
for key, value in kwargs.items():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% if chat_mode %}
"chat_mode=True"
{% else %}
"chat_mode=False"
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{% include 'my_app/inherited.html' with chat_mode=True %}
{% include 'my_app/inherited.html' with chat_mode=False %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% if pat.name %}
pat.name={{ pat.name }}
{% else %}
no_pat_name
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% if entries %}
<ul>
{% for entry in entries %}
<li>
{{ entry.key }}
:
{{ entry.invalid_attribute }}
</li>
{% endfor %}
</ul>
{% else %}
<p>No entries are available.</p>
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
{% doesnotexist %}
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^name$', views.get_name, name='name'),
]
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'),
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys
from .forms import NameForm


class Entry(object):

def __init__(self, key, val):
Expand All @@ -17,13 +18,15 @@ def __unicode__(self):
def __str__(self):
return u'%s:%s' % (self.key, self.val)


def index(request):
context = {
'entries': [Entry('v1', 'v1'), Entry('v2', 'v2')]
}
ret = render(request, 'my_app/index.html', context)
return ret


def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
Expand All @@ -38,6 +41,33 @@ def get_name(request):

# if a GET (or any other method) we'll create a blank form
else:
form = NameForm(data= {'your_name': 'unknown name'})
form = NameForm(data={'your_name': 'unknown name'})

return render(request, 'my_app/name.html', {'form': form})


return render(request, 'my_app/name.html', {'form': form})
def inherits(request):
context = {}
ret = render(request, 'my_app/inherits.html', context)
return ret


def template_error(request):
context = {
'entries': [Entry('v1', 'v1'), Entry('v2', 'v2')]
}

ret = render(request, 'my_app/template_error.html', context)
return ret


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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% if chat_mode %}
"chat_mode=True"
{% else %}
"chat_mode=False"
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{% include 'my_app/inherited.html' with chat_mode=True %}
{% include 'my_app/inherited.html' with chat_mode=False %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% if pat.name %}
pat.name={{ pat.name }}
{% else %}
no_pat_name
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
url(r'^name$', views.get_name, name='name'),
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'),
]
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,15 @@ def template_error2(request):
context = {}
ret = render(request, 'my_app/template_error2.html', context)
return ret


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
Loading