PY-62566 Reduce code duplication; remove PyDBFrame from plugin API function arguments; regenerate binaries

GitOrigin-RevId: 4b9831d52d44142619b11200a563c149971fe4b4
This commit is contained in:
Andrey Lisin
2023-10-10 11:50:36 +00:00
committed by intellij-monorepo-bot
parent 6104b06e48
commit f3cb61ff59
51 changed files with 23238 additions and 15777 deletions
@@ -13,7 +13,7 @@ boolean isMac = Os.isFamily(Os.FAMILY_MAC)
envs {
String python27version = "2.7.18"
String python36version = "3.6.8" // latest available installer
String python36version = (isWindows) ? "3.6.8" : "3.6.15" // 3.6.8 is broken on modern libc and clang, but latest version for Windows
String python37version = "3.7.9"
String python38version = "3.8.10"
String python39version = "3.9.13"
@@ -7,7 +7,7 @@ from _pydev_bundle import pydev_log
from _pydevd_bundle.pydevd_frame import PyDBFrame
# ENDIF
version = 37
version = 38
if not hasattr(sys, '_current_frames'):
@@ -5,7 +5,8 @@ from collections import namedtuple
from _pydevd_bundle.pydevd_constants import IS_PY3K, IS_CPYTHON
__all__ = ["get_smart_step_into_candidates"]
__all__ = ["find_last_call_name", "find_last_func_call_order",
"get_smart_step_into_candidates"]
_LOAD_OPNAMES = {
'LOAD_BUILD_CLASS',
File diff suppressed because it is too large Load Diff
@@ -13,7 +13,7 @@ pydev_log.debug("Using Cython speedups")
# from _pydevd_bundle.pydevd_frame import PyDBFrame
# ENDIF
version = 37
version = 38
if not hasattr(sys, '_current_frames'):
@@ -193,7 +193,7 @@ from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE, PYDEV_FILE
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace
from _pydevd_bundle.pydevd_bytecode_utils import find_last_call_name, find_last_func_call_order
from _pydevd_bundle.pydevd_utils import get_clsname_for_code, should_stop_on_failed_test, is_exception_in_test_unit_can_be_ignored, eval_expression
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, is_real_file
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame
try:
from inspect import CO_GENERATOR
@@ -270,6 +270,242 @@ def handle_breakpoint_expression(breakpoint, info, new_frame):
info.pydev_message = str(val)
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
def should_stop_on_exception(tuple args, frame, str event, tuple arg):
cdef PyDBAdditionalThreadInfo info;
cdef bint flag;
# ELSE
# def should_stop_on_exception(args, frame, event, arg):
# ENDIF
# main_debugger, _filename, info, _thread = args
main_debugger = args[0]
info = args[2]
should_stop = False
# STATE_SUSPEND = 2
if info.pydev_state != 2: # and breakpoint is not None:
exception, value, trace = arg
if trace is not None and hasattr(trace, 'tb_next'):
# on jython trace is None on the first event and it may not have a tb_next.
exception_breakpoint = get_exception_breakpoint(
exception, main_debugger.break_on_caught_exceptions)
if exception_breakpoint is not None:
if exception_breakpoint.condition is not None:
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
eval_result = handle_breakpoint_condition(main_debugger, info, exception_breakpoint, frame)
remove_exception_from_frame(frame)
if not eval_result:
return False, frame
if exception_breakpoint.ignore_libraries:
if not main_debugger.is_exception_trace_in_project_scope(trace):
return False, frame
if ignore_exception_trace(trace):
return False, frame
was_just_raised = just_raised(trace)
if was_just_raised:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# Option: Don't break if an exception is caught in the same function from which it is thrown
return False, frame
if exception_breakpoint.notify_on_first_raise_only:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# In this case we never stop if it was just raised, so, to know if it was the first we
# need to check if we're in the 2nd method.
if not was_just_raised and not just_raised(trace.tb_next):
return False, frame # I.e.: we stop only when we're at the caller of a method that throws an exception
else:
if not was_just_raised and not main_debugger.is_top_level_trace_in_project_scope(trace):
return False, frame # I.e.: we stop only when it was just raised
# If it got here we should stop.
should_stop = True
try:
info.pydev_message = exception_breakpoint.qname
except:
info.pydev_message = exception_breakpoint.qname.encode('utf-8')
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
info.pydev_message = "python-%s" % info.pydev_message
else:
# No regular exception breakpoint, let's see if some plugin handles it or if it is a test assertion error.
try:
if main_debugger.plugin is not None:
result = main_debugger.plugin.exception_break(main_debugger, frame, args, arg)
if result:
should_stop, frame = result
if main_debugger.stop_on_failed_tests and main_debugger.is_test_item_or_set_up_caller(trace) \
and not is_exception_in_test_unit_can_be_ignored(exception):
should_stop, frame = should_stop_on_failed_test(arg), frame
info.pydev_message = "python-AssertionError"
except:
should_stop = False
if should_stop:
if exception_breakpoint is not None and exception_breakpoint.expression is not None:
handle_breakpoint_expression(exception_breakpoint, info, frame)
return should_stop, frame
# Same thing in the main debugger but only considering the file contents,
# while the one in the main debugger considers the user input (so, the actual result
# must be a join of both).
filename_to_lines_where_exceptions_are_ignored = {}
filename_to_stat_info = {}
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
def handle_exception(tuple args, frame, str event, tuple arg):
# ELSE
# def handle_exception(args, frame, event, arg):
# ENDIF
try:
# We have 3 things in arg: exception type, description, traceback object
trace_obj = arg[2]
main_debugger = args[0]
initial_trace_obj = trace_obj
if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
# I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check).
pass
else:
# Get the trace_obj from where the exception was raised...
while trace_obj.tb_next is not None:
trace_obj = trace_obj.tb_next
if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception \
and not main_debugger.stop_on_failed_tests:
for check_trace_obj in (initial_trace_obj, trace_obj):
filename = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame)[1]
lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
if lines_ignored is None:
lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
try:
curr_stat = os.stat(filename)
curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
except:
curr_stat = None
last_stat = filename_to_stat_info.get(filename)
if last_stat != curr_stat:
filename_to_stat_info[filename] = curr_stat
lines_ignored.clear()
try:
linecache.checkcache(filename)
except:
# Jython 2.1
linecache.checkcache()
from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
if from_user_input:
merged = {}
merged.update(lines_ignored)
# Override what we have with the related entries that the user entered
merged.update(from_user_input)
else:
merged = lines_ignored
exc_lineno = check_trace_obj.tb_lineno
# print ('lines ignored', lines_ignored)
# print ('user input', from_user_input)
# print ('merged', merged, 'curr', exc_lineno)
if exc_lineno not in merged: # Note: check on merged but update lines_ignored.
try:
line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
except:
# Jython 2.1
line = linecache.getline(filename, exc_lineno)
if IGNORE_EXCEPTION_TAG.match(line) is not None:
lines_ignored[exc_lineno] = 1
return
else:
# Put in the cache saying not to ignore
lines_ignored[exc_lineno] = 0
else:
# Ok, dict has it already cached, so, let's check it...
if merged.get(exc_lineno, 0):
return
thread = args[3]
try:
frame_id_to_frame = {}
frame_id_to_frame[id(frame)] = frame
f = trace_obj.tb_frame
while f is not None:
frame_id_to_frame[id(f)] = f
f = f.f_back
f = None
thread_id = get_current_thread_id(thread)
if main_debugger.stop_on_failed_tests:
# Our goal is to find the deepest frame in stack that still belongs to the project and stop there.
f = trace_obj.tb_frame
while f:
abs_path, _, _ = get_abs_path_real_path_and_base_from_frame(f)
if main_debugger.in_project_scope(abs_path):
frame = f
break
f = f.f_back
f = None
trace_obj = initial_trace_obj
while trace_obj:
if trace_obj.tb_frame is frame:
break
trace_obj = trace_obj.tb_next
add_exception_to_frame(frame, (arg[0], arg[1], trace_obj))
pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame)
try:
main_debugger.send_caught_exception_stack(thread, arg, id(frame))
main_debugger.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
main_debugger.do_wait_suspend(thread, frame, event, arg)
main_debugger.send_caught_exception_stack_proceeded(thread)
finally:
pydevd_vars.remove_additional_frame_by_id(thread_id)
except KeyboardInterrupt as e:
raise e
except:
traceback.print_exc()
main_debugger.set_trace_for_frame_and_parents(frame)
finally:
# Make sure the user cannot see the '__exception__' we added after we leave the suspend state.
remove_exception_from_frame(frame)
# Clear some local variables...
frame = None
trace_obj = None
initial_trace_obj = None
check_trace_obj = None
f = None
frame_id_to_frame = None
main_debugger = None
thread = None
#=======================================================================================================================
# PyDBFrame
#=======================================================================================================================
@@ -285,11 +521,6 @@ cdef class PyDBFrame:
# Note: class (and not instance) attributes.
# Same thing in the main debugger but only considering the file contents, while the one in the main debugger
# considers the user input (so, the actual result must be a join of both).
filename_to_lines_where_exceptions_are_ignored = {}
filename_to_stat_info = {}
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
cdef tuple _args
cdef int should_skip
@@ -323,10 +554,10 @@ cdef class PyDBFrame:
# def trace_exception(self, frame, event, arg):
# ENDIF
if event == 'exception':
should_stop, frame = self.should_stop_on_exception(frame, event, arg)
should_stop, frame = should_stop_on_exception(self._args, frame, event, arg)
if should_stop:
self.handle_exception(frame, event, arg)
handle_exception(self._args, frame, event, arg)
return self.trace_dispatch
return self.trace_exception
@@ -337,231 +568,6 @@ cdef class PyDBFrame:
send_signature_return_trace(main_debugger, frame, filename, arg)
return self.trace_return
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
def should_stop_on_exception(self, frame, str event, arg):
cdef PyDBAdditionalThreadInfo info;
cdef bint flag;
# ELSE
# def should_stop_on_exception(self, frame, event, arg):
# ENDIF
# main_debugger, _filename, info, _thread = self._args
main_debugger = self._args[0]
info = self._args[2]
should_stop = False
# STATE_SUSPEND = 2
if info.pydev_state != 2: # and breakpoint is not None:
exception, value, trace = arg
if trace is not None and hasattr(trace, 'tb_next'):
# on jython trace is None on the first event and it may not have a tb_next.
exception_breakpoint = get_exception_breakpoint(
exception, main_debugger.break_on_caught_exceptions)
if exception_breakpoint is not None:
if exception_breakpoint.condition is not None:
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
eval_result = handle_breakpoint_condition(main_debugger, info, exception_breakpoint, frame)
remove_exception_from_frame(frame)
if not eval_result:
return False, frame
if exception_breakpoint.ignore_libraries:
if not main_debugger.is_exception_trace_in_project_scope(trace):
return False, frame
if ignore_exception_trace(trace):
return False, frame
was_just_raised = just_raised(trace)
if was_just_raised:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# Option: Don't break if an exception is caught in the same function from which it is thrown
return False, frame
if exception_breakpoint.notify_on_first_raise_only:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# In this case we never stop if it was just raised, so, to know if it was the first we
# need to check if we're in the 2nd method.
if not was_just_raised and not just_raised(trace.tb_next):
return False, frame # I.e.: we stop only when we're at the caller of a method that throws an exception
else:
if not was_just_raised and not main_debugger.is_top_level_trace_in_project_scope(trace):
return False, frame # I.e.: we stop only when it was just raised
# If it got here we should stop.
should_stop = True
try:
info.pydev_message = exception_breakpoint.qname
except:
info.pydev_message = exception_breakpoint.qname.encode('utf-8')
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
info.pydev_message = "python-%s" % info.pydev_message
else:
# No regular exception breakpoint, let's see if some plugin handles it or if it is a test assertion error.
try:
if main_debugger.plugin is not None:
result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg)
if result:
should_stop, frame = result
if main_debugger.stop_on_failed_tests and main_debugger.is_test_item_or_set_up_caller(trace) \
and not is_exception_in_test_unit_can_be_ignored(exception):
should_stop, frame = should_stop_on_failed_test(arg), frame
info.pydev_message = "python-AssertionError"
except:
should_stop = False
if should_stop:
if exception_breakpoint is not None and exception_breakpoint.expression is not None:
handle_breakpoint_expression(exception_breakpoint, info, frame)
return should_stop, frame
def handle_exception(self, frame, event, arg):
try:
# We have 3 things in arg: exception type, description, traceback object
trace_obj = arg[2]
main_debugger = self._args[0]
initial_trace_obj = trace_obj
if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
# I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check).
pass
else:
# Get the trace_obj from where the exception was raised...
while trace_obj.tb_next is not None:
trace_obj = trace_obj.tb_next
if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception \
and not main_debugger.stop_on_failed_tests:
for check_trace_obj in (initial_trace_obj, trace_obj):
filename = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame)[1]
filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored
lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
if lines_ignored is None:
lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
try:
curr_stat = os.stat(filename)
curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
except:
curr_stat = None
last_stat = self.filename_to_stat_info.get(filename)
if last_stat != curr_stat:
self.filename_to_stat_info[filename] = curr_stat
lines_ignored.clear()
try:
linecache.checkcache(filename)
except:
# Jython 2.1
linecache.checkcache()
from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
if from_user_input:
merged = {}
merged.update(lines_ignored)
# Override what we have with the related entries that the user entered
merged.update(from_user_input)
else:
merged = lines_ignored
exc_lineno = check_trace_obj.tb_lineno
# print ('lines ignored', lines_ignored)
# print ('user input', from_user_input)
# print ('merged', merged, 'curr', exc_lineno)
if exc_lineno not in merged: # Note: check on merged but update lines_ignored.
try:
line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
except:
# Jython 2.1
line = linecache.getline(filename, exc_lineno)
if IGNORE_EXCEPTION_TAG.match(line) is not None:
lines_ignored[exc_lineno] = 1
return
else:
# Put in the cache saying not to ignore
lines_ignored[exc_lineno] = 0
else:
# Ok, dict has it already cached, so, let's check it...
if merged.get(exc_lineno, 0):
return
thread = self._args[3]
try:
frame_id_to_frame = {}
frame_id_to_frame[id(frame)] = frame
f = trace_obj.tb_frame
while f is not None:
frame_id_to_frame[id(f)] = f
f = f.f_back
f = None
thread_id = get_current_thread_id(thread)
if main_debugger.stop_on_failed_tests:
# Our goal is to find the deepest frame in stack that still belongs to the project and stop there.
f = trace_obj.tb_frame
while f:
abs_path, _, _ = get_abs_path_real_path_and_base_from_frame(f)
if main_debugger.in_project_scope(abs_path):
frame = f
break
f = f.f_back
f = None
trace_obj = initial_trace_obj
while trace_obj:
if trace_obj.tb_frame is frame:
break
trace_obj = trace_obj.tb_next
add_exception_to_frame(frame, (arg[0], arg[1], trace_obj))
pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame)
try:
main_debugger.send_caught_exception_stack(thread, arg, id(frame))
self.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
self.do_wait_suspend(thread, frame, event, arg)
main_debugger.send_caught_exception_stack_proceeded(thread)
finally:
pydevd_vars.remove_additional_frame_by_id(thread_id)
except KeyboardInterrupt as e:
raise e
except:
traceback.print_exc()
main_debugger.set_trace_for_frame_and_parents(frame)
finally:
# Make sure the user cannot see the '__exception__' we added after we leave the suspend state.
remove_exception_from_frame(frame)
# Clear some local variables...
frame = None
trace_obj = None
initial_trace_obj = None
check_trace_obj = None
f = None
frame_id_to_frame = None
main_debugger = None
thread = None
def get_func_name(self, frame):
code_obj = frame.f_code
func_name = code_obj.co_name
@@ -683,9 +689,10 @@ cdef class PyDBFrame:
if is_exception_event:
if has_exception_breakpoints:
should_stop, frame = self.should_stop_on_exception(frame, event, arg)
should_stop, frame = should_stop_on_exception(
self._args, frame, event, arg)
if should_stop:
self.handle_exception(frame, event, arg)
handle_exception(self._args, frame, event, arg)
# No need to reset frame.f_trace to keep the same trace function.
return self.trace_dispatch
is_line = False
@@ -753,7 +760,7 @@ cdef class PyDBFrame:
if can_skip:
if plugin_manager is not None and main_debugger.has_plugin_line_breaks:
can_skip = not plugin_manager.can_not_skip(main_debugger, self, frame, info)
can_skip = not plugin_manager.can_not_skip(main_debugger, frame, info)
# CMD_STEP_OVER = 108
if can_skip and main_debugger.show_return_values and info.pydev_step_cmd == 108 and frame.f_back is info.pydev_step_stop:
@@ -852,7 +859,7 @@ cdef class PyDBFrame:
elif step_cmd == CMD_SMART_STEP_INTO and (frame.f_back is smart_stop_frame and is_within_context):
stop = False
elif plugin_manager is not None and main_debugger.has_plugin_line_breaks:
result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args)
result = plugin_manager.get_breakpoint(main_debugger, frame, event, self._args)
if result:
exist_result = True
flag, breakpoint, new_frame, bp_type = result
@@ -20,7 +20,7 @@ from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE, PYDEV_FILE
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace
from _pydevd_bundle.pydevd_bytecode_utils import find_last_call_name, find_last_func_call_order
from _pydevd_bundle.pydevd_utils import get_clsname_for_code, should_stop_on_failed_test, is_exception_in_test_unit_can_be_ignored, eval_expression
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, is_real_file
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame
try:
from inspect import CO_GENERATOR
@@ -97,6 +97,242 @@ def handle_breakpoint_expression(breakpoint, info, new_frame):
info.pydev_message = str(val)
# IFDEF CYTHON
# def should_stop_on_exception(tuple args, frame, str event, tuple arg):
# cdef PyDBAdditionalThreadInfo info;
# cdef bint flag;
# ELSE
def should_stop_on_exception(args, frame, event, arg):
# ENDIF
# main_debugger, _filename, info, _thread = args
main_debugger = args[0]
info = args[2]
should_stop = False
# STATE_SUSPEND = 2
if info.pydev_state != 2: # and breakpoint is not None:
exception, value, trace = arg
if trace is not None and hasattr(trace, 'tb_next'):
# on jython trace is None on the first event and it may not have a tb_next.
exception_breakpoint = get_exception_breakpoint(
exception, main_debugger.break_on_caught_exceptions)
if exception_breakpoint is not None:
if exception_breakpoint.condition is not None:
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
eval_result = handle_breakpoint_condition(main_debugger, info, exception_breakpoint, frame)
remove_exception_from_frame(frame)
if not eval_result:
return False, frame
if exception_breakpoint.ignore_libraries:
if not main_debugger.is_exception_trace_in_project_scope(trace):
return False, frame
if ignore_exception_trace(trace):
return False, frame
was_just_raised = just_raised(trace)
if was_just_raised:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# Option: Don't break if an exception is caught in the same function from which it is thrown
return False, frame
if exception_breakpoint.notify_on_first_raise_only:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# In this case we never stop if it was just raised, so, to know if it was the first we
# need to check if we're in the 2nd method.
if not was_just_raised and not just_raised(trace.tb_next):
return False, frame # I.e.: we stop only when we're at the caller of a method that throws an exception
else:
if not was_just_raised and not main_debugger.is_top_level_trace_in_project_scope(trace):
return False, frame # I.e.: we stop only when it was just raised
# If it got here we should stop.
should_stop = True
try:
info.pydev_message = exception_breakpoint.qname
except:
info.pydev_message = exception_breakpoint.qname.encode('utf-8')
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
info.pydev_message = "python-%s" % info.pydev_message
else:
# No regular exception breakpoint, let's see if some plugin handles it or if it is a test assertion error.
try:
if main_debugger.plugin is not None:
result = main_debugger.plugin.exception_break(main_debugger, frame, args, arg)
if result:
should_stop, frame = result
if main_debugger.stop_on_failed_tests and main_debugger.is_test_item_or_set_up_caller(trace) \
and not is_exception_in_test_unit_can_be_ignored(exception):
should_stop, frame = should_stop_on_failed_test(arg), frame
info.pydev_message = "python-AssertionError"
except:
should_stop = False
if should_stop:
if exception_breakpoint is not None and exception_breakpoint.expression is not None:
handle_breakpoint_expression(exception_breakpoint, info, frame)
return should_stop, frame
# Same thing in the main debugger but only considering the file contents,
# while the one in the main debugger considers the user input (so, the actual result
# must be a join of both).
filename_to_lines_where_exceptions_are_ignored = {}
filename_to_stat_info = {}
# IFDEF CYTHON
# def handle_exception(tuple args, frame, str event, tuple arg):
# ELSE
def handle_exception(args, frame, event, arg):
# ENDIF
try:
# We have 3 things in arg: exception type, description, traceback object
trace_obj = arg[2]
main_debugger = args[0]
initial_trace_obj = trace_obj
if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
# I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check).
pass
else:
# Get the trace_obj from where the exception was raised...
while trace_obj.tb_next is not None:
trace_obj = trace_obj.tb_next
if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception \
and not main_debugger.stop_on_failed_tests:
for check_trace_obj in (initial_trace_obj, trace_obj):
filename = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame)[1]
lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
if lines_ignored is None:
lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
try:
curr_stat = os.stat(filename)
curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
except:
curr_stat = None
last_stat = filename_to_stat_info.get(filename)
if last_stat != curr_stat:
filename_to_stat_info[filename] = curr_stat
lines_ignored.clear()
try:
linecache.checkcache(filename)
except:
# Jython 2.1
linecache.checkcache()
from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
if from_user_input:
merged = {}
merged.update(lines_ignored)
# Override what we have with the related entries that the user entered
merged.update(from_user_input)
else:
merged = lines_ignored
exc_lineno = check_trace_obj.tb_lineno
# print ('lines ignored', lines_ignored)
# print ('user input', from_user_input)
# print ('merged', merged, 'curr', exc_lineno)
if exc_lineno not in merged: # Note: check on merged but update lines_ignored.
try:
line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
except:
# Jython 2.1
line = linecache.getline(filename, exc_lineno)
if IGNORE_EXCEPTION_TAG.match(line) is not None:
lines_ignored[exc_lineno] = 1
return
else:
# Put in the cache saying not to ignore
lines_ignored[exc_lineno] = 0
else:
# Ok, dict has it already cached, so, let's check it...
if merged.get(exc_lineno, 0):
return
thread = args[3]
try:
frame_id_to_frame = {}
frame_id_to_frame[id(frame)] = frame
f = trace_obj.tb_frame
while f is not None:
frame_id_to_frame[id(f)] = f
f = f.f_back
f = None
thread_id = get_current_thread_id(thread)
if main_debugger.stop_on_failed_tests:
# Our goal is to find the deepest frame in stack that still belongs to the project and stop there.
f = trace_obj.tb_frame
while f:
abs_path, _, _ = get_abs_path_real_path_and_base_from_frame(f)
if main_debugger.in_project_scope(abs_path):
frame = f
break
f = f.f_back
f = None
trace_obj = initial_trace_obj
while trace_obj:
if trace_obj.tb_frame is frame:
break
trace_obj = trace_obj.tb_next
add_exception_to_frame(frame, (arg[0], arg[1], trace_obj))
pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame)
try:
main_debugger.send_caught_exception_stack(thread, arg, id(frame))
main_debugger.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
main_debugger.do_wait_suspend(thread, frame, event, arg)
main_debugger.send_caught_exception_stack_proceeded(thread)
finally:
pydevd_vars.remove_additional_frame_by_id(thread_id)
except KeyboardInterrupt as e:
raise e
except:
traceback.print_exc()
main_debugger.set_trace_for_frame_and_parents(frame)
finally:
# Make sure the user cannot see the '__exception__' we added after we leave the suspend state.
remove_exception_from_frame(frame)
# Clear some local variables...
frame = None
trace_obj = None
initial_trace_obj = None
check_trace_obj = None
f = None
frame_id_to_frame = None
main_debugger = None
thread = None
#=======================================================================================================================
# PyDBFrame
#=======================================================================================================================
@@ -112,11 +348,6 @@ class PyDBFrame:
# Note: class (and not instance) attributes.
# Same thing in the main debugger but only considering the file contents, while the one in the main debugger
# considers the user input (so, the actual result must be a join of both).
filename_to_lines_where_exceptions_are_ignored = {}
filename_to_stat_info = {}
# IFDEF CYTHON
# cdef tuple _args
# cdef int should_skip
@@ -150,10 +381,10 @@ class PyDBFrame:
def trace_exception(self, frame, event, arg):
# ENDIF
if event == 'exception':
should_stop, frame = self.should_stop_on_exception(frame, event, arg)
should_stop, frame = should_stop_on_exception(self._args, frame, event, arg)
if should_stop:
self.handle_exception(frame, event, arg)
handle_exception(self._args, frame, event, arg)
return self.trace_dispatch
return self.trace_exception
@@ -164,231 +395,6 @@ class PyDBFrame:
send_signature_return_trace(main_debugger, frame, filename, arg)
return self.trace_return
# IFDEF CYTHON
# def should_stop_on_exception(self, frame, str event, arg):
# cdef PyDBAdditionalThreadInfo info;
# cdef bint flag;
# ELSE
def should_stop_on_exception(self, frame, event, arg):
# ENDIF
# main_debugger, _filename, info, _thread = self._args
main_debugger = self._args[0]
info = self._args[2]
should_stop = False
# STATE_SUSPEND = 2
if info.pydev_state != 2: # and breakpoint is not None:
exception, value, trace = arg
if trace is not None and hasattr(trace, 'tb_next'):
# on jython trace is None on the first event and it may not have a tb_next.
exception_breakpoint = get_exception_breakpoint(
exception, main_debugger.break_on_caught_exceptions)
if exception_breakpoint is not None:
if exception_breakpoint.condition is not None:
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
eval_result = handle_breakpoint_condition(main_debugger, info, exception_breakpoint, frame)
remove_exception_from_frame(frame)
if not eval_result:
return False, frame
if exception_breakpoint.ignore_libraries:
if not main_debugger.is_exception_trace_in_project_scope(trace):
return False, frame
if ignore_exception_trace(trace):
return False, frame
was_just_raised = just_raised(trace)
if was_just_raised:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# Option: Don't break if an exception is caught in the same function from which it is thrown
return False, frame
if exception_breakpoint.notify_on_first_raise_only:
if main_debugger.skip_on_exceptions_thrown_in_same_context:
# In this case we never stop if it was just raised, so, to know if it was the first we
# need to check if we're in the 2nd method.
if not was_just_raised and not just_raised(trace.tb_next):
return False, frame # I.e.: we stop only when we're at the caller of a method that throws an exception
else:
if not was_just_raised and not main_debugger.is_top_level_trace_in_project_scope(trace):
return False, frame # I.e.: we stop only when it was just raised
# If it got here we should stop.
should_stop = True
try:
info.pydev_message = exception_breakpoint.qname
except:
info.pydev_message = exception_breakpoint.qname.encode('utf-8')
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
info.pydev_message = "python-%s" % info.pydev_message
else:
# No regular exception breakpoint, let's see if some plugin handles it or if it is a test assertion error.
try:
if main_debugger.plugin is not None:
result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg)
if result:
should_stop, frame = result
if main_debugger.stop_on_failed_tests and main_debugger.is_test_item_or_set_up_caller(trace) \
and not is_exception_in_test_unit_can_be_ignored(exception):
should_stop, frame = should_stop_on_failed_test(arg), frame
info.pydev_message = "python-AssertionError"
except:
should_stop = False
if should_stop:
if exception_breakpoint is not None and exception_breakpoint.expression is not None:
handle_breakpoint_expression(exception_breakpoint, info, frame)
return should_stop, frame
def handle_exception(self, frame, event, arg):
try:
# We have 3 things in arg: exception type, description, traceback object
trace_obj = arg[2]
main_debugger = self._args[0]
initial_trace_obj = trace_obj
if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
# I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check).
pass
else:
# Get the trace_obj from where the exception was raised...
while trace_obj.tb_next is not None:
trace_obj = trace_obj.tb_next
if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception \
and not main_debugger.stop_on_failed_tests:
for check_trace_obj in (initial_trace_obj, trace_obj):
filename = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame)[1]
filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored
lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
if lines_ignored is None:
lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
try:
curr_stat = os.stat(filename)
curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
except:
curr_stat = None
last_stat = self.filename_to_stat_info.get(filename)
if last_stat != curr_stat:
self.filename_to_stat_info[filename] = curr_stat
lines_ignored.clear()
try:
linecache.checkcache(filename)
except:
# Jython 2.1
linecache.checkcache()
from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
if from_user_input:
merged = {}
merged.update(lines_ignored)
# Override what we have with the related entries that the user entered
merged.update(from_user_input)
else:
merged = lines_ignored
exc_lineno = check_trace_obj.tb_lineno
# print ('lines ignored', lines_ignored)
# print ('user input', from_user_input)
# print ('merged', merged, 'curr', exc_lineno)
if exc_lineno not in merged: # Note: check on merged but update lines_ignored.
try:
line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
except:
# Jython 2.1
line = linecache.getline(filename, exc_lineno)
if IGNORE_EXCEPTION_TAG.match(line) is not None:
lines_ignored[exc_lineno] = 1
return
else:
# Put in the cache saying not to ignore
lines_ignored[exc_lineno] = 0
else:
# Ok, dict has it already cached, so, let's check it...
if merged.get(exc_lineno, 0):
return
thread = self._args[3]
try:
frame_id_to_frame = {}
frame_id_to_frame[id(frame)] = frame
f = trace_obj.tb_frame
while f is not None:
frame_id_to_frame[id(f)] = f
f = f.f_back
f = None
thread_id = get_current_thread_id(thread)
if main_debugger.stop_on_failed_tests:
# Our goal is to find the deepest frame in stack that still belongs to the project and stop there.
f = trace_obj.tb_frame
while f:
abs_path, _, _ = get_abs_path_real_path_and_base_from_frame(f)
if main_debugger.in_project_scope(abs_path):
frame = f
break
f = f.f_back
f = None
trace_obj = initial_trace_obj
while trace_obj:
if trace_obj.tb_frame is frame:
break
trace_obj = trace_obj.tb_next
add_exception_to_frame(frame, (arg[0], arg[1], trace_obj))
pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame)
try:
main_debugger.send_caught_exception_stack(thread, arg, id(frame))
self.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
self.do_wait_suspend(thread, frame, event, arg)
main_debugger.send_caught_exception_stack_proceeded(thread)
finally:
pydevd_vars.remove_additional_frame_by_id(thread_id)
except KeyboardInterrupt as e:
raise e
except:
traceback.print_exc()
main_debugger.set_trace_for_frame_and_parents(frame)
finally:
# Make sure the user cannot see the '__exception__' we added after we leave the suspend state.
remove_exception_from_frame(frame)
# Clear some local variables...
frame = None
trace_obj = None
initial_trace_obj = None
check_trace_obj = None
f = None
frame_id_to_frame = None
main_debugger = None
thread = None
def get_func_name(self, frame):
code_obj = frame.f_code
func_name = code_obj.co_name
@@ -510,9 +516,10 @@ class PyDBFrame:
if is_exception_event:
if has_exception_breakpoints:
should_stop, frame = self.should_stop_on_exception(frame, event, arg)
should_stop, frame = should_stop_on_exception(
self._args, frame, event, arg)
if should_stop:
self.handle_exception(frame, event, arg)
handle_exception(self._args, frame, event, arg)
# No need to reset frame.f_trace to keep the same trace function.
return self.trace_dispatch
is_line = False
@@ -580,7 +587,7 @@ class PyDBFrame:
if can_skip:
if plugin_manager is not None and main_debugger.has_plugin_line_breaks:
can_skip = not plugin_manager.can_not_skip(main_debugger, self, frame, info)
can_skip = not plugin_manager.can_not_skip(main_debugger, frame, info)
# CMD_STEP_OVER = 108
if can_skip and main_debugger.show_return_values and info.pydev_step_cmd == 108 and frame.f_back is info.pydev_step_stop:
@@ -679,7 +686,7 @@ class PyDBFrame:
elif step_cmd == CMD_SMART_STEP_INTO and (frame.f_back is smart_stop_frame and is_within_context):
stop = False
elif plugin_manager is not None and main_debugger.has_plugin_line_breaks:
result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args)
result = plugin_manager.get_breakpoint(main_debugger, frame, event, self._args)
if result:
exist_result = True
flag, breakpoint, new_frame, bp_type = result
@@ -1,4 +1,3 @@
import linecache
import os
import sys
import threading
@@ -7,23 +6,19 @@ from os.path import splitext, basename
from _pydev_bundle import pydev_log
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
from _pydevd_bundle import pydevd_vars
from _pydevd_bundle.pydevd_additional_thread_info_regular import \
set_additional_thread_info
from _pydevd_bundle.pydevd_breakpoints import get_exception_breakpoint, \
stop_on_unhandled_exception
from _pydevd_bundle.pydevd_breakpoints import stop_on_unhandled_exception
from _pydevd_bundle.pydevd_bytecode_utils import find_last_call_name, \
find_last_func_call_order
from _pydevd_bundle.pydevd_comm_constants import CMD_STEP_OVER, CMD_SMART_STEP_INTO, \
CMD_SET_BREAK, CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE, \
CMD_STEP_CAUGHT_EXCEPTION
CMD_SET_BREAK, CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_INTO_COROUTINE
from _pydevd_bundle.pydevd_constants import get_current_thread_id, PYDEVD_TOOL_NAME, \
STATE_RUN, STATE_SUSPEND
from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE
from _pydevd_bundle.pydevd_frame import handle_breakpoint_condition, \
handle_breakpoint_expression, DEBUG_START, DEBUG_START_PY3K, IGNORE_EXCEPTION_TAG
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, \
remove_exception_from_frame, ignore_exception_trace, just_raised
handle_breakpoint_expression, DEBUG_START, DEBUG_START_PY3K, \
should_stop_on_exception, handle_exception
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
from pydevd_file_utils import NORM_PATHS_AND_BASE_CONTAINER, \
get_abs_path_real_path_and_base_from_frame
@@ -201,7 +196,7 @@ class PyStartCallback(PEP669CallbackBase):
if can_skip:
if plugin_manager is not None and self.py_db.has_plugin_line_breaks:
can_skip = not plugin_manager.can_not_skip(
self.py_db, self, frame, info)
self.py_db, frame, info)
# CMD_STEP_OVER = 108
if (can_skip and self.py_db.show_return_values
@@ -465,9 +460,6 @@ class PyLineCallback(PEP669CallbackBase):
class PyRaiseCallback(PEP669CallbackBase):
filename_to_lines_where_exceptions_are_ignored = {}
filename_to_stat_info = {}
_top_level_frame = None
def _get_top_level_frame(self):
@@ -502,9 +494,15 @@ class PyRaiseCallback(PEP669CallbackBase):
or self.py_db.has_plugin_exception_breaks
or self.py_db.stop_on_failed_tests)
if has_exception_breakpoints:
should_stop, frame = self.should_stop_on_exception(self.frame, exc_info)
args = (
self.py_db, self._get_filename(frame),
self._get_additional_info(self.thread), self.thread, global_cache_skips,
global_cache_frame_skips
)
should_stop, frame = should_stop_on_exception(
args, self.frame, 'exception', exc_info)
if should_stop:
self.handle_exception(frame, 'exception', exc_info)
handle_exception(args, frame, 'exception', exc_info)
def _stop_on_unhandled_exception(self, exc_info):
additional_info = self._get_additional_info(self.thread)
@@ -513,212 +511,6 @@ class PyRaiseCallback(PEP669CallbackBase):
stop_on_unhandled_exception(self.py_db, self.thread, additional_info,
exc_info)
# XXX: Copy-paste from `PyDBFrame`. This method should be factored out. Plugins
# are not supported.
def should_stop_on_exception(self, frame, arg):
thread = self.thread
info = self._get_additional_info(thread)
should_stop = False
# STATE_SUSPEND = 2
if info.pydev_state == 2:
return should_stop, frame
exception, value, trace = arg
if trace is not None and hasattr(trace, 'tb_next'):
exception_breakpoint = get_exception_breakpoint(
exception, self.py_db.break_on_caught_exceptions)
if exception_breakpoint is not None:
if exception_breakpoint.condition is not None:
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
eval_result = handle_breakpoint_condition(self.py_db, info, exception_breakpoint, frame)
remove_exception_from_frame(frame)
if not eval_result:
return False, frame
if exception_breakpoint.ignore_libraries:
if not self.py_db.is_exception_trace_in_project_scope(trace):
return False, frame
if ignore_exception_trace(trace):
return False, frame
was_just_raised = just_raised(trace)
if was_just_raised:
if self.py_db.skip_on_exceptions_thrown_in_same_context:
# Option: Don't break if an exception is caught in the same function from which it is thrown
return False, frame
if exception_breakpoint.notify_on_first_raise_only:
if self.py_db.skip_on_exceptions_thrown_in_same_context:
# In this case we never stop if it was just raised, so, to know if it was the first we
# need to check if we're in the 2nd method.
if not was_just_raised and not just_raised(trace.tb_next):
return False, frame # I.e.: we stop only when we're at the caller of a method that throws an exception
else:
if not was_just_raised and not self.py_db.is_top_level_trace_in_project_scope(trace):
return False, frame # I.e.: we stop only when it was just raised
# If it got here we should stop.
should_stop = True
try:
info.pydev_message = exception_breakpoint.qname
except:
info.pydev_message = exception_breakpoint.qname.encode('utf-8')
# Always add exception to frame (must remove later after we proceed).
add_exception_to_frame(frame, (exception, value, trace))
info.pydev_message = "python-%s" % info.pydev_message
if should_stop:
if exception_breakpoint is not None and exception_breakpoint.expression is not None:
handle_breakpoint_expression(exception_breakpoint, info, frame)
return should_stop, frame
# XXX: Copy-paste from `PyDBFrame`. This method should be factored out.
def handle_exception(self, frame, event, arg):
try:
# We have 3 things in arg: exception type, description, traceback object
trace_obj = arg[2]
initial_trace_obj = trace_obj
if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
# I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check).
pass
else:
# Get the trace_obj from where the exception was raised...
while trace_obj.tb_next is not None:
trace_obj = trace_obj.tb_next
if self.py_db.ignore_exceptions_thrown_in_lines_with_ignore_exception \
and not self.py_db.stop_on_failed_tests:
for check_trace_obj in (initial_trace_obj, trace_obj):
filename = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame)[1]
filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored
lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
if lines_ignored is None:
lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
try:
curr_stat = os.stat(filename)
curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
except:
curr_stat = None
last_stat = self.filename_to_stat_info.get(filename)
if last_stat != curr_stat:
self.filename_to_stat_info[filename] = curr_stat
lines_ignored.clear()
try:
linecache.checkcache(filename)
except:
# Jython 2.1
linecache.checkcache()
from_user_input = self.py_db.filename_to_lines_where_exceptions_are_ignored.get(filename)
if from_user_input:
merged = {}
merged.update(lines_ignored)
# Override what we have with the related entries that the user entered
merged.update(from_user_input)
else:
merged = lines_ignored
exc_lineno = check_trace_obj.tb_lineno
# print ('lines ignored', lines_ignored)
# print ('user input', from_user_input)
# print ('merged', merged, 'curr', exc_lineno)
if exc_lineno not in merged: # Note: check on merged but update lines_ignored.
try:
line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
except:
# Jython 2.1
line = linecache.getline(filename, exc_lineno)
if IGNORE_EXCEPTION_TAG.match(line) is not None:
lines_ignored[exc_lineno] = 1
return
else:
# Put in the cache saying not to ignore
lines_ignored[exc_lineno] = 0
else:
# Ok, dict has it already cached, so, let's check it...
if merged.get(exc_lineno, 0):
return
thread = self.thread
try:
frame_id_to_frame = {}
frame_id_to_frame[id(frame)] = frame
f = trace_obj.tb_frame
while f is not None:
frame_id_to_frame[id(f)] = f
f = f.f_back
f = None
thread_id = get_current_thread_id(thread)
if self.py_db.stop_on_failed_tests:
# Our goal is to find the deepest frame in stack that still belongs to the project and stop there.
f = trace_obj.tb_frame
while f:
abs_path, _, _ = get_abs_path_real_path_and_base_from_frame(f)
if self.py_db.in_project_scope(abs_path):
frame = f
break
f = f.f_back
f = None
trace_obj = initial_trace_obj
while trace_obj:
if trace_obj.tb_frame is frame:
break
trace_obj = trace_obj.tb_next
add_exception_to_frame(frame, (arg[0], arg[1], trace_obj))
pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame)
try:
self.py_db.send_caught_exception_stack(thread, arg, id(frame))
self.py_db.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
self.py_db.do_wait_suspend(thread, frame, event, arg)
self.py_db.send_caught_exception_stack_proceeded(thread)
finally:
pydevd_vars.remove_additional_frame_by_id(thread_id)
except KeyboardInterrupt as e:
raise e
except:
traceback.print_exc()
self.py_db.set_trace_for_frame_and_parents(frame)
finally:
# Make sure the user cannot see the '__exception__' we added after we leave the suspend state.
remove_exception_from_frame(frame)
# Clear some local variables...
frame = None
trace_obj = None
initial_trace_obj = None
check_trace_obj = None
f = None
frame_id_to_frame = None
main_debugger = None
thread = None
class PyReturnCallback(PEP669CallbackBase):
def __call__(self, code, instruction_offset, retval):
@@ -10,7 +10,7 @@ def remove_exception_breakpoint(plugin, pydb, type, exception):
def get_breakpoints(plugin, pydb):
return None
def can_not_skip(plugin, pydb, pydb_frame, frame, info):
def can_not_skip(plugin, pydb, frame, info):
return False
def has_exception_breaks(plugin):
@@ -28,13 +28,13 @@ def cmd_step_over(plugin, pydb, frame, event, args, stop_info, stop):
def stop(plugin, pydb, frame, event, args, stop_info, arg, step_cmd):
return False
def get_breakpoint(plugin, pydb, pydb_frame, frame, event, args):
def get_breakpoint(plugin, pydb, frame, event, args):
return None
def suspend(plugin, pydb, thread, frame):
return None
def exception_break(plugin, pydb, pydb_frame, frame, args, arg):
def exception_break(plugin, pydb, frame, args, arg):
return None
def change_variable(plugin, frame, attr, expression):
@@ -238,7 +238,7 @@ def get_func_code_info_py(code_obj) -> FuncCodeInfo:
# noinspection DuplicatedCode
cdef PyObject * get_bytecode_while_frame_eval(PyFrameObject * frame_obj, int exc):
cdef PyObject * get_bytecode_while_frame_eval(PyFrameObject * frame_obj, int exc) noexcept:
'''
This function makes the actual evaluation and changes the bytecode to a version
where programmatic breakpoints are added.
@@ -238,7 +238,7 @@ def get_func_code_info_py(code_obj) -> FuncCodeInfo:
# noinspection DuplicatedCode
cdef PyObject * get_bytecode_while_frame_eval(PyThreadState *tstate, PyFrameObject * frame_obj, int exc):
cdef PyObject * get_bytecode_while_frame_eval(PyThreadState *tstate, PyFrameObject * frame_obj, int exc) noexcept:
'''
This function makes the actual evaluation and changes the bytecode to a version
where programmatic breakpoints are added.
@@ -333,7 +333,7 @@ def _is_django_exception_break_context(frame):
# Django Step Commands
#=======================================================================================================================
def can_not_skip(plugin, main_debugger, pydb_frame, frame, info):
def can_not_skip(plugin, main_debugger, frame, info):
return main_debugger.django_breakpoints and _is_django_render_call(frame)
@@ -393,7 +393,7 @@ def stop(plugin, main_debugger, frame, event, args, stop_info, arg, step_cmd):
return False
def get_breakpoint(plugin, main_debugger, pydb_frame, frame, event, args):
def get_breakpoint(plugin, main_debugger, frame, event, args):
main_debugger = args[0]
filename = args[1]
info = args[2]
@@ -424,7 +424,7 @@ def suspend(plugin, main_debugger, thread, frame, bp_type):
return suspend_django(main_debugger, thread, frame)
return None
def exception_break(plugin, main_debugger, pydb_frame, frame, args, arg):
def exception_break(plugin, main_debugger, frame, args, arg):
main_debugger = args[0]
thread = args[3]
exception, value, trace = arg
@@ -230,7 +230,7 @@ def has_line_breaks(plugin):
return True
return False
def can_not_skip(plugin, pydb, pydb_frame, frame, info):
def can_not_skip(plugin, pydb, frame, info):
if pydb.jinja2_breakpoints and _is_jinja2_render_call(frame):
filename = _get_jinja2_template_filename(frame)
jinja2_breakpoints_for_file = pydb.jinja2_breakpoints.get(filename)
@@ -325,7 +325,7 @@ def stop(plugin, pydb, frame, event, args, stop_info, arg, step_cmd):
return False
def get_breakpoint(plugin, pydb, pydb_frame, frame, event, args):
def get_breakpoint(plugin, pydb, frame, event, args):
pydb= args[0]
filename = args[1]
info = args[2]
@@ -356,7 +356,7 @@ def suspend(plugin, pydb, thread, frame, bp_type):
return None
def exception_break(plugin, pydb, pydb_frame, frame, args, arg):
def exception_break(plugin, pydb, frame, args, arg):
pydb = args[0]
thread = args[3]
exception, value, trace = arg
@@ -378,7 +378,7 @@ def exception_break(plugin, pydb, pydb_frame, frame, args, arg):
name = frame.f_code.co_name
if name in ('template', 'top-level template code', '<module>') or name.startswith('block '):
#Jinja2 translates exception info and creates fake frame on his own
pydb_frame.set_suspend(thread, CMD_ADD_EXCEPTION_BREAK)
pydb.set_suspend(thread, CMD_ADD_EXCEPTION_BREAK)
add_exception_to_frame(frame, (exception, value, trace))
thread.additional_info.suspend_type = JINJA2_SUSPEND
thread.additional_info.pydev_message = str(exception_type)