mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
This commit is contained in:
parent
9aaf937478
commit
274cf886ce
16 changed files with 4735 additions and 3870 deletions
|
|
@ -75,6 +75,9 @@ CMD_PYDEVD_JSON_CONFIG = 156
|
|||
CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION = 157
|
||||
CMD_THREAD_RESUME_SINGLE_NOTIFICATION = 158
|
||||
|
||||
CMD_STEP_OVER_MY_CODE = 159
|
||||
CMD_STEP_RETURN_MY_CODE = 160
|
||||
|
||||
CMD_REDIRECT_OUTPUT = 200
|
||||
CMD_GET_NEXT_STATEMENT_TARGETS = 201
|
||||
CMD_SET_PROJECT_ROOTS = 202
|
||||
|
|
@ -155,6 +158,9 @@ ID_TO_MEANING = {
|
|||
'157': 'CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION',
|
||||
'158': 'CMD_THREAD_RESUME_SINGLE_NOTIFICATION',
|
||||
|
||||
'159': 'CMD_STEP_OVER_MY_CODE',
|
||||
'160': 'CMD_STEP_RETURN_MY_CODE',
|
||||
|
||||
'200': 'CMD_REDIRECT_OUTPUT',
|
||||
'201': 'CMD_GET_NEXT_STATEMENT_TARGETS',
|
||||
'202': 'CMD_SET_PROJECT_ROOTS',
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -159,7 +159,8 @@ from _pydev_bundle import pydev_log
|
|||
from _pydevd_bundle import pydevd_dont_trace
|
||||
from _pydevd_bundle import pydevd_vars
|
||||
from _pydevd_bundle.pydevd_comm_constants import (CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
|
||||
CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO_MY_CODE)
|
||||
CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO_MY_CODE,
|
||||
CMD_STEP_RETURN_MY_CODE, CMD_STEP_OVER_MY_CODE)
|
||||
from _pydevd_bundle.pydevd_constants import STATE_SUSPEND, get_current_thread_id, STATE_RUN, dict_iter_values, IS_PY3K, \
|
||||
dict_keys, RETURN_VALUES_DICT, NO_FTRACE
|
||||
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace
|
||||
|
|
@ -561,10 +562,13 @@ cdef class PyDBFrame:
|
|||
|
||||
if is_exception_event:
|
||||
breakpoints_for_file = None
|
||||
# CMD_STEP_OVER = 108
|
||||
if stop_frame and stop_frame is not frame and step_cmd == 108 and \
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_OVER_MY_CODE = 159
|
||||
if stop_frame and stop_frame is not frame and step_cmd in (108, 159) and \
|
||||
arg[0] in (StopIteration, GeneratorExit) and arg[2] is None:
|
||||
info.pydev_step_cmd = 107 # CMD_STEP_INTO = 107
|
||||
if step_cmd == CMD_STEP_OVER:
|
||||
info.pydev_step_cmd = CMD_STEP_INTO
|
||||
else:
|
||||
info.pydev_step_cmd = CMD_STEP_INTO_MY_CODE
|
||||
info.pydev_step_stop = None
|
||||
else:
|
||||
# If we are in single step mode and something causes us to exit the current frame, we need to make sure we break
|
||||
|
|
@ -573,9 +577,14 @@ cdef class PyDBFrame:
|
|||
# to make a step in or step over at that location).
|
||||
# Note: this is especially troublesome when we're skipping code with the
|
||||
# @DontTrace comment.
|
||||
if stop_frame is frame and is_return and step_cmd in (109, 108): # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
|
||||
if stop_frame is frame and is_return and step_cmd in (108, 109, 159, 160):
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_RETURN = 109, CMD_STEP_OVER_MY_CODE = 159, CMD_STEP_RETURN_MY_CODE = 160
|
||||
|
||||
if not frame.f_code.co_flags & 0x20: # CO_GENERATOR = 0x20 (inspect.CO_GENERATOR)
|
||||
info.pydev_step_cmd = 107 # CMD_STEP_INTO = 107
|
||||
if step_cmd in (108, 109):
|
||||
info.pydev_step_cmd = CMD_STEP_INTO
|
||||
else:
|
||||
info.pydev_step_cmd = CMD_STEP_INTO_MY_CODE
|
||||
info.pydev_step_stop = None
|
||||
|
||||
breakpoints_for_file = main_debugger.breakpoints.get(filename)
|
||||
|
|
@ -586,16 +595,16 @@ cdef class PyDBFrame:
|
|||
# we can skip if:
|
||||
# - we have no stop marked
|
||||
# - we should make a step return/step over and we're not in the current frame
|
||||
# CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_RETURN = 109, CMD_STEP_OVER_MY_CODE = 159, CMD_STEP_RETURN_MY_CODE = 160
|
||||
can_skip = (step_cmd == -1 and stop_frame is None) \
|
||||
or (step_cmd in (109, 108) and stop_frame is not frame)
|
||||
or (step_cmd in (108, 109, 159, 160) and stop_frame is not frame)
|
||||
|
||||
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)
|
||||
|
||||
# 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:
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_OVER_MY_CODE = 159
|
||||
if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (108, 159) and frame.f_back is info.pydev_step_stop:
|
||||
# trace function for showing return values after step over
|
||||
can_skip = False
|
||||
|
||||
|
|
@ -672,7 +681,7 @@ cdef class PyDBFrame:
|
|||
breakpoint = breakpoints_for_file[line]
|
||||
new_frame = frame
|
||||
stop = True
|
||||
if step_cmd == CMD_STEP_OVER and stop_frame is frame and (is_line or is_return):
|
||||
if step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and (stop_frame is frame and is_line):
|
||||
stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
|
||||
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)
|
||||
|
|
@ -719,7 +728,7 @@ cdef class PyDBFrame:
|
|||
return self.trace_dispatch
|
||||
|
||||
if main_debugger.show_return_values:
|
||||
if is_return and info.pydev_step_cmd == CMD_STEP_OVER and frame.f_back == info.pydev_step_stop:
|
||||
if is_return and info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and frame.f_back == info.pydev_step_stop:
|
||||
self.show_return_values(frame, arg)
|
||||
|
||||
elif main_debugger.remove_return_values_flag:
|
||||
|
|
@ -730,11 +739,11 @@ cdef class PyDBFrame:
|
|||
|
||||
if stop:
|
||||
self.set_suspend(
|
||||
thread,
|
||||
CMD_SET_BREAK,
|
||||
thread,
|
||||
CMD_SET_BREAK,
|
||||
suspend_other_threads=breakpoint and breakpoint.suspend_policy == "ALL",
|
||||
)
|
||||
|
||||
|
||||
elif flag and plugin_manager is not None:
|
||||
result = plugin_manager.suspend(main_debugger, thread, frame, bp_type)
|
||||
if result:
|
||||
|
|
@ -774,18 +783,42 @@ cdef class PyDBFrame:
|
|||
stop = False
|
||||
|
||||
elif step_cmd == CMD_STEP_INTO:
|
||||
stop = is_line or is_return
|
||||
if is_line:
|
||||
stop = True
|
||||
elif is_return:
|
||||
if frame.f_back is not None:
|
||||
if main_debugger.get_file_type(
|
||||
get_abs_path_real_path_and_base_from_frame(frame.f_back)) == main_debugger.PYDEV_FILE:
|
||||
stop = False
|
||||
else:
|
||||
stop = True
|
||||
if plugin_manager is not None:
|
||||
result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop)
|
||||
if result:
|
||||
stop, plugin_stop = result
|
||||
|
||||
elif step_cmd == CMD_STEP_INTO_MY_CODE:
|
||||
if main_debugger.in_project_scope(frame.f_code.co_filename):
|
||||
stop = is_line
|
||||
if is_line:
|
||||
if main_debugger.in_project_scope(frame.f_code.co_filename):
|
||||
stop = True
|
||||
elif is_return and frame.f_back is not None:
|
||||
if main_debugger.in_project_scope(frame.f_back.f_code.co_filename):
|
||||
stop = True
|
||||
else:
|
||||
stop = False
|
||||
|
||||
elif step_cmd == CMD_STEP_OVER:
|
||||
stop = stop_frame is frame and (is_line or is_return)
|
||||
if plugin_manager is not None:
|
||||
result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop)
|
||||
if result:
|
||||
stop, plugin_stop = result
|
||||
|
||||
elif step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE):
|
||||
# Note: when dealing with a step over my code it's the same as a step over (the
|
||||
# difference is that when we return from a frame in one we go to regular step
|
||||
# into and in the other we go to a step into my code).
|
||||
stop = stop_frame is frame and is_line
|
||||
# Note: don't stop on a return for step over, only for line events
|
||||
# i.e.: don't stop in: (stop_frame is frame.f_back and is_return) as we'd stop twice in that line.
|
||||
|
||||
if frame.f_code.co_flags & CO_GENERATOR:
|
||||
if is_return:
|
||||
|
|
@ -812,7 +845,7 @@ cdef class PyDBFrame:
|
|||
if curr_func_name == info.pydev_func_name:
|
||||
stop = True
|
||||
|
||||
elif step_cmd == CMD_STEP_RETURN:
|
||||
elif step_cmd in (CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE):
|
||||
stop = is_return and stop_frame is frame
|
||||
|
||||
else:
|
||||
|
|
@ -1241,7 +1274,7 @@ cdef class ThreadTracer:
|
|||
# ENDIF
|
||||
|
||||
# DEBUG = 'code_to_debug' in frame.f_code.co_filename
|
||||
# if DEBUG: print('ENTER: trace_dispatch', frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)
|
||||
# if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name))
|
||||
py_db, t, additional_info, cache_skips, frame_skips_cache = self._args
|
||||
pydev_step_cmd = additional_info.pydev_step_cmd
|
||||
is_stepping = pydev_step_cmd != -1
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ from _pydev_bundle import pydev_log
|
|||
from _pydevd_bundle import pydevd_dont_trace
|
||||
from _pydevd_bundle import pydevd_vars
|
||||
from _pydevd_bundle.pydevd_comm_constants import (CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
|
||||
CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO_MY_CODE)
|
||||
CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO_MY_CODE,
|
||||
CMD_STEP_RETURN_MY_CODE, CMD_STEP_OVER_MY_CODE)
|
||||
from _pydevd_bundle.pydevd_constants import STATE_SUSPEND, get_current_thread_id, STATE_RUN, dict_iter_values, IS_PY3K, \
|
||||
dict_keys, RETURN_VALUES_DICT, NO_FTRACE
|
||||
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace
|
||||
|
|
@ -410,10 +411,13 @@ class PyDBFrame:
|
|||
|
||||
if is_exception_event:
|
||||
breakpoints_for_file = None
|
||||
# CMD_STEP_OVER = 108
|
||||
if stop_frame and stop_frame is not frame and step_cmd == 108 and \
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_OVER_MY_CODE = 159
|
||||
if stop_frame and stop_frame is not frame and step_cmd in (108, 159) and \
|
||||
arg[0] in (StopIteration, GeneratorExit) and arg[2] is None:
|
||||
info.pydev_step_cmd = 107 # CMD_STEP_INTO = 107
|
||||
if step_cmd == CMD_STEP_OVER:
|
||||
info.pydev_step_cmd = CMD_STEP_INTO
|
||||
else:
|
||||
info.pydev_step_cmd = CMD_STEP_INTO_MY_CODE
|
||||
info.pydev_step_stop = None
|
||||
else:
|
||||
# If we are in single step mode and something causes us to exit the current frame, we need to make sure we break
|
||||
|
|
@ -422,9 +426,14 @@ class PyDBFrame:
|
|||
# to make a step in or step over at that location).
|
||||
# Note: this is especially troublesome when we're skipping code with the
|
||||
# @DontTrace comment.
|
||||
if stop_frame is frame and is_return and step_cmd in (109, 108): # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
|
||||
if stop_frame is frame and is_return and step_cmd in (108, 109, 159, 160):
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_RETURN = 109, CMD_STEP_OVER_MY_CODE = 159, CMD_STEP_RETURN_MY_CODE = 160
|
||||
|
||||
if not frame.f_code.co_flags & 0x20: # CO_GENERATOR = 0x20 (inspect.CO_GENERATOR)
|
||||
info.pydev_step_cmd = 107 # CMD_STEP_INTO = 107
|
||||
if step_cmd in (108, 109):
|
||||
info.pydev_step_cmd = CMD_STEP_INTO
|
||||
else:
|
||||
info.pydev_step_cmd = CMD_STEP_INTO_MY_CODE
|
||||
info.pydev_step_stop = None
|
||||
|
||||
breakpoints_for_file = main_debugger.breakpoints.get(filename)
|
||||
|
|
@ -435,16 +444,16 @@ class PyDBFrame:
|
|||
# we can skip if:
|
||||
# - we have no stop marked
|
||||
# - we should make a step return/step over and we're not in the current frame
|
||||
# CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_RETURN = 109, CMD_STEP_OVER_MY_CODE = 159, CMD_STEP_RETURN_MY_CODE = 160
|
||||
can_skip = (step_cmd == -1 and stop_frame is None) \
|
||||
or (step_cmd in (109, 108) and stop_frame is not frame)
|
||||
or (step_cmd in (108, 109, 159, 160) and stop_frame is not frame)
|
||||
|
||||
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)
|
||||
|
||||
# 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:
|
||||
# CMD_STEP_OVER = 108, CMD_STEP_OVER_MY_CODE = 159
|
||||
if can_skip and main_debugger.show_return_values and info.pydev_step_cmd in (108, 159) and frame.f_back is info.pydev_step_stop:
|
||||
# trace function for showing return values after step over
|
||||
can_skip = False
|
||||
|
||||
|
|
@ -521,7 +530,7 @@ class PyDBFrame:
|
|||
breakpoint = breakpoints_for_file[line]
|
||||
new_frame = frame
|
||||
stop = True
|
||||
if step_cmd == CMD_STEP_OVER and stop_frame is frame and (is_line or is_return):
|
||||
if step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and (stop_frame is frame and is_line):
|
||||
stop = False # we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
|
||||
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)
|
||||
|
|
@ -568,7 +577,7 @@ class PyDBFrame:
|
|||
return self.trace_dispatch
|
||||
|
||||
if main_debugger.show_return_values:
|
||||
if is_return and info.pydev_step_cmd == CMD_STEP_OVER and frame.f_back == info.pydev_step_stop:
|
||||
if is_return and info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and frame.f_back == info.pydev_step_stop:
|
||||
self.show_return_values(frame, arg)
|
||||
|
||||
elif main_debugger.remove_return_values_flag:
|
||||
|
|
@ -579,11 +588,11 @@ class PyDBFrame:
|
|||
|
||||
if stop:
|
||||
self.set_suspend(
|
||||
thread,
|
||||
CMD_SET_BREAK,
|
||||
thread,
|
||||
CMD_SET_BREAK,
|
||||
suspend_other_threads=breakpoint and breakpoint.suspend_policy == "ALL",
|
||||
)
|
||||
|
||||
|
||||
elif flag and plugin_manager is not None:
|
||||
result = plugin_manager.suspend(main_debugger, thread, frame, bp_type)
|
||||
if result:
|
||||
|
|
@ -623,18 +632,42 @@ class PyDBFrame:
|
|||
stop = False
|
||||
|
||||
elif step_cmd == CMD_STEP_INTO:
|
||||
stop = is_line or is_return
|
||||
if is_line:
|
||||
stop = True
|
||||
elif is_return:
|
||||
if frame.f_back is not None:
|
||||
if main_debugger.get_file_type(
|
||||
get_abs_path_real_path_and_base_from_frame(frame.f_back)) == main_debugger.PYDEV_FILE:
|
||||
stop = False
|
||||
else:
|
||||
stop = True
|
||||
if plugin_manager is not None:
|
||||
result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop)
|
||||
if result:
|
||||
stop, plugin_stop = result
|
||||
|
||||
elif step_cmd == CMD_STEP_INTO_MY_CODE:
|
||||
if main_debugger.in_project_scope(frame.f_code.co_filename):
|
||||
stop = is_line
|
||||
if is_line:
|
||||
if main_debugger.in_project_scope(frame.f_code.co_filename):
|
||||
stop = True
|
||||
elif is_return and frame.f_back is not None:
|
||||
if main_debugger.in_project_scope(frame.f_back.f_code.co_filename):
|
||||
stop = True
|
||||
else:
|
||||
stop = False
|
||||
|
||||
elif step_cmd == CMD_STEP_OVER:
|
||||
stop = stop_frame is frame and (is_line or is_return)
|
||||
if plugin_manager is not None:
|
||||
result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop)
|
||||
if result:
|
||||
stop, plugin_stop = result
|
||||
|
||||
elif step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE):
|
||||
# Note: when dealing with a step over my code it's the same as a step over (the
|
||||
# difference is that when we return from a frame in one we go to regular step
|
||||
# into and in the other we go to a step into my code).
|
||||
stop = stop_frame is frame and is_line
|
||||
# Note: don't stop on a return for step over, only for line events
|
||||
# i.e.: don't stop in: (stop_frame is frame.f_back and is_return) as we'd stop twice in that line.
|
||||
|
||||
if frame.f_code.co_flags & CO_GENERATOR:
|
||||
if is_return:
|
||||
|
|
@ -661,7 +694,7 @@ class PyDBFrame:
|
|||
if curr_func_name == info.pydev_func_name:
|
||||
stop = True
|
||||
|
||||
elif step_cmd == CMD_STEP_RETURN:
|
||||
elif step_cmd in (CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE):
|
||||
stop = is_return and stop_frame is frame
|
||||
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from _pydevd_bundle.pydevd_comm_constants import (CMD_RUN, CMD_SET_PROTOCOL, CMD
|
|||
CMD_EVALUATE_CONSOLE_EXPRESSION, CMD_RUN_CUSTOM_OPERATION, CMD_IGNORE_THROWN_EXCEPTION_AT,
|
||||
CMD_ENABLE_DONT_TRACE, CMD_REDIRECT_OUTPUT, CMD_GET_NEXT_STATEMENT_TARGETS,
|
||||
CMD_SET_PROJECT_ROOTS, CMD_THREAD_DUMP_TO_STDERR, CMD_STOP_ON_START, CMD_PYDEVD_JSON_CONFIG,
|
||||
CMD_GET_EXCEPTION_DETAILS)
|
||||
CMD_GET_EXCEPTION_DETAILS, CMD_STEP_RETURN_MY_CODE, CMD_STEP_OVER_MY_CODE)
|
||||
from _pydevd_bundle.pydevd_constants import (get_thread_id, IS_PY3K, DebugInfoHolder, dict_keys, STATE_RUN,
|
||||
NEXT_VALUE_SEPARATOR, IS_WINDOWS, get_current_thread_id, HTTP_JSON_PROTOCOL, JSON_PROTOCOL,
|
||||
set_protocol, get_protocol)
|
||||
|
|
@ -172,8 +172,14 @@ def process_net_command(py_db, cmd_id, seq, text):
|
|||
additional_info.pydev_step_stop = None
|
||||
additional_info.pydev_state = STATE_RUN
|
||||
|
||||
elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN or \
|
||||
cmd_id == CMD_STEP_INTO_MY_CODE:
|
||||
elif cmd_id in (
|
||||
CMD_STEP_INTO,
|
||||
CMD_STEP_OVER,
|
||||
CMD_STEP_RETURN,
|
||||
CMD_STEP_INTO_MY_CODE,
|
||||
CMD_STEP_OVER_MY_CODE,
|
||||
CMD_STEP_RETURN_MY_CODE
|
||||
):
|
||||
# we received some command to make a single step
|
||||
t = pydevd_find_thread_by_id(text)
|
||||
if t:
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ class ThreadTracer(object):
|
|||
# ENDIF
|
||||
|
||||
# DEBUG = 'code_to_debug' in frame.f_code.co_filename
|
||||
# if DEBUG: print('ENTER: trace_dispatch', frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)
|
||||
# if DEBUG: print('ENTER: trace_dispatch: %s %s %s %s' % (frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name))
|
||||
py_db, t, additional_info, cache_skips, frame_skips_cache = self._args
|
||||
pydev_step_cmd = additional_info.pydev_step_cmd
|
||||
is_stepping = pydev_step_cmd != -1
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -256,6 +256,7 @@ cdef PyObject * get_bytecode_while_frame_eval(PyFrameObject * frame_obj, int exc
|
|||
cdef int STATE_SUSPEND = 2
|
||||
cdef int CMD_STEP_INTO = 107
|
||||
cdef int CMD_STEP_OVER = 108
|
||||
cdef int CMD_STEP_OVER_MY_CODE = 159
|
||||
cdef int CMD_STEP_INTO_MY_CODE = 144
|
||||
cdef bint can_skip = True
|
||||
try:
|
||||
|
|
@ -301,7 +302,7 @@ cdef PyObject * get_bytecode_while_frame_eval(PyFrameObject * frame_obj, int exc
|
|||
main_debugger.break_on_caught_exceptions or \
|
||||
main_debugger.has_plugin_exception_breaks or \
|
||||
main_debugger.signature_factory or \
|
||||
additional_info.pydev_step_cmd == CMD_STEP_OVER and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop:
|
||||
additional_info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE) and main_debugger.show_return_values and frame.f_back is additional_info.pydev_step_stop:
|
||||
|
||||
# if DEBUG:
|
||||
# print('get_bytecode_while_frame_eval enabled trace')
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_i
|
|||
from _pydevd_bundle.pydevd_breakpoints import ExceptionBreakpoint, get_exception_breakpoint
|
||||
from _pydevd_bundle.pydevd_comm_constants import (CMD_THREAD_SUSPEND, CMD_STEP_INTO, CMD_SET_BREAK,
|
||||
CMD_STEP_INTO_MY_CODE, CMD_STEP_OVER, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE,
|
||||
CMD_SET_NEXT_STATEMENT, CMD_STEP_RETURN, CMD_ADD_EXCEPTION_BREAK)
|
||||
CMD_SET_NEXT_STATEMENT, CMD_STEP_RETURN, CMD_ADD_EXCEPTION_BREAK, CMD_STEP_RETURN_MY_CODE,
|
||||
CMD_STEP_OVER_MY_CODE)
|
||||
from _pydevd_bundle.pydevd_constants import (IS_JYTH_LESS25, IS_PYCHARM, get_thread_id, get_current_thread_id,
|
||||
dict_keys, dict_iter_items, DebugInfoHolder, PYTHON_SUSPEND, STATE_SUSPEND, STATE_RUN, get_frame,
|
||||
clear_cached_thread_id, INTERACTIVE_MODE_AVAILABLE, SHOW_DEBUG_INFO_ENV, IS_PY34_OR_GREATER, IS_PY2, NULL,
|
||||
|
|
@ -51,7 +52,7 @@ from _pydevd_frame_eval.pydevd_frame_eval_main import (
|
|||
import pydev_ipython # @UnusedImport
|
||||
from pydevd_concurrency_analyser.pydevd_concurrency_logger import ThreadingLogger, AsyncioLogger, send_message, cur_time
|
||||
from pydevd_concurrency_analyser.pydevd_thread_wrappers import wrap_threads
|
||||
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER
|
||||
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER, get_abs_path_real_path_and_base_from_file
|
||||
from pydevd_file_utils import get_fullname, rPath, get_package_dir
|
||||
import pydevd_tracing
|
||||
|
||||
|
|
@ -514,7 +515,7 @@ class PyDB(object):
|
|||
finally:
|
||||
if val is not None:
|
||||
info.pydev_message = str(val)
|
||||
|
||||
|
||||
def get_file_type(self, abs_real_path_and_basename):
|
||||
'''
|
||||
:param abs_real_path_and_basename:
|
||||
|
|
@ -623,8 +624,18 @@ class PyDB(object):
|
|||
self.plugin = PluginManager(self)
|
||||
return self.plugin
|
||||
|
||||
def in_project_scope(self, filename):
|
||||
return pydevd_utils.in_project_roots(filename)
|
||||
def in_project_scope(self, filename, cache={}):
|
||||
try:
|
||||
return cache[filename]
|
||||
except KeyError:
|
||||
abs_real_path_and_basename = get_abs_path_real_path_and_base_from_file(filename)
|
||||
# pydevd files are nevere considered to be in the project scope.
|
||||
if self.get_file_type(abs_real_path_and_basename) == self.PYDEV_FILE:
|
||||
cache[filename] = False
|
||||
else:
|
||||
cache[filename] = pydevd_utils.in_project_roots(filename)
|
||||
|
||||
return cache[filename]
|
||||
|
||||
def is_ignored_by_filters(self, filename):
|
||||
return pydevd_utils.is_ignored_by_filter(filename)
|
||||
|
|
@ -1094,6 +1105,7 @@ class PyDB(object):
|
|||
If True we should use the line of the exception instead of the current line in the frame
|
||||
as the paused location on the top-level frame (exception info must be passed on 'arg').
|
||||
"""
|
||||
# print('do_wait_suspend %s %s %s %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event))
|
||||
self.process_internal_commands()
|
||||
thread_stack_str = '' # @UnusedVariable -- this is here so that `make_get_thread_stack_message`
|
||||
# can retrieve it later.
|
||||
|
|
@ -1149,19 +1161,20 @@ class PyDB(object):
|
|||
self.cancel_async_evaluation(get_current_thread_id(thread), str(id(frame)))
|
||||
|
||||
# process any stepping instructions
|
||||
if info.pydev_step_cmd == CMD_STEP_INTO or info.pydev_step_cmd == CMD_STEP_INTO_MY_CODE:
|
||||
if info.pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE):
|
||||
info.pydev_step_stop = None
|
||||
info.pydev_smart_step_stop = None
|
||||
self.set_trace_for_frame_and_parents(frame)
|
||||
|
||||
elif info.pydev_step_cmd == CMD_STEP_OVER:
|
||||
elif info.pydev_step_cmd in (CMD_STEP_OVER, CMD_STEP_OVER_MY_CODE):
|
||||
info.pydev_step_stop = frame
|
||||
info.pydev_smart_step_stop = None
|
||||
self.set_trace_for_frame_and_parents(frame)
|
||||
|
||||
elif info.pydev_step_cmd == CMD_SMART_STEP_INTO:
|
||||
self.set_trace_for_frame_and_parents(frame)
|
||||
info.pydev_step_stop = None
|
||||
info.pydev_smart_step_stop = frame
|
||||
self.set_trace_for_frame_and_parents(frame)
|
||||
|
||||
elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT:
|
||||
self.set_trace_for_frame_and_parents(frame)
|
||||
|
|
@ -1195,8 +1208,16 @@ class PyDB(object):
|
|||
self._do_wait_suspend(thread, frame, event, arg, suspend_type, from_this_thread)
|
||||
return
|
||||
|
||||
elif info.pydev_step_cmd == CMD_STEP_RETURN:
|
||||
elif info.pydev_step_cmd in (CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE):
|
||||
back_frame = frame.f_back
|
||||
if info.pydev_step_cmd == CMD_STEP_RETURN_MY_CODE:
|
||||
while back_frame is not None:
|
||||
if self.in_project_scope(back_frame.f_code.co_filename):
|
||||
break
|
||||
else:
|
||||
frame = back_frame
|
||||
back_frame = back_frame.f_back
|
||||
|
||||
if back_frame is not None:
|
||||
# steps back to the same frame (in a return call it will stop in the 'back frame' for the user)
|
||||
info.pydev_step_stop = frame
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ CMD_PYDEVD_JSON_CONFIG = 156
|
|||
CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION = 157
|
||||
CMD_THREAD_RESUME_SINGLE_NOTIFICATION = 158
|
||||
|
||||
CMD_STEP_OVER_MY_CODE = 159
|
||||
CMD_STEP_RETURN_MY_CODE = 160
|
||||
|
||||
CMD_REDIRECT_OUTPUT = 200
|
||||
CMD_GET_NEXT_STATEMENT_TARGETS = 201
|
||||
CMD_SET_PROJECT_ROOTS = 202
|
||||
|
|
@ -93,7 +96,10 @@ REASON_STOP_ON_BREAKPOINT = CMD_SET_BREAK
|
|||
REASON_THREAD_SUSPEND = CMD_THREAD_SUSPEND
|
||||
REASON_STEP_INTO = CMD_STEP_INTO
|
||||
REASON_STEP_INTO_MY_CODE = CMD_STEP_INTO_MY_CODE
|
||||
REASON_STEP_RETURN = CMD_STEP_RETURN
|
||||
REASON_STEP_RETURN_MY_CODE = CMD_STEP_RETURN_MY_CODE
|
||||
REASON_STEP_OVER = CMD_STEP_OVER
|
||||
REASON_STEP_OVER_MY_CODE = CMD_STEP_OVER_MY_CODE
|
||||
|
||||
# Always True (because otherwise when we do have an error, it's hard to diagnose).
|
||||
SHOW_WRITES_AND_READS = True
|
||||
|
|
@ -715,6 +721,7 @@ class AbstractWriterThread(threading.Thread):
|
|||
# note: those must be passed in kwargs.
|
||||
line = kwargs.get('line')
|
||||
file = kwargs.get('file')
|
||||
name = kwargs.get('name')
|
||||
|
||||
self.log.append('Start: wait_for_breakpoint_hit')
|
||||
# wait for hit breakpoint
|
||||
|
|
@ -728,9 +735,9 @@ class AbstractWriterThread(threading.Thread):
|
|||
return False
|
||||
|
||||
msg = self.wait_for_message(accept_message, timeout=timeout)
|
||||
return self._get_stack_as_hit(msg, file, line)
|
||||
return self._get_stack_as_hit(msg, file, line, name)
|
||||
|
||||
def _get_stack_as_hit(self, msg, file=None, line=None):
|
||||
def _get_stack_as_hit(self, msg, file=None, line=None, name=None):
|
||||
# we have something like <xml><thread id="12152656" stop_reason="111"><frame id="12453120" name="encode" ...
|
||||
if len(msg.thread.frame) == 0:
|
||||
frame = msg.thread.frame
|
||||
|
|
@ -739,7 +746,7 @@ class AbstractWriterThread(threading.Thread):
|
|||
thread_id = msg.thread['id']
|
||||
frame_id = frame['id']
|
||||
suspend_type = msg.thread['suspend_type']
|
||||
name = frame['name']
|
||||
hit_name = frame['name']
|
||||
frame_line = int(frame['line'])
|
||||
frame_file = frame['file']
|
||||
|
||||
|
|
@ -749,10 +756,13 @@ class AbstractWriterThread(threading.Thread):
|
|||
if line is not None:
|
||||
assert line == frame_line, 'Expected hit to be in line %s, was: %s' % (line, frame_line)
|
||||
|
||||
if name is not None:
|
||||
assert name == hit_name
|
||||
|
||||
self.log.append('End(1): wait_for_breakpoint_hit: %s' % (msg.original_xml,))
|
||||
|
||||
return Hit(
|
||||
thread_id=thread_id, frame_id=frame_id, line=frame_line, suspend_type=suspend_type, name=name, file=frame_file)
|
||||
thread_id=thread_id, frame_id=frame_id, line=frame_line, suspend_type=suspend_type, name=hit_name, file=frame_file)
|
||||
|
||||
def wait_for_get_next_statement_targets(self):
|
||||
last = ''
|
||||
|
|
@ -960,9 +970,18 @@ class AbstractWriterThread(threading.Thread):
|
|||
def write_step_in(self, thread_id):
|
||||
self.write("%s\t%s\t%s" % (CMD_STEP_INTO, self.next_seq(), thread_id,))
|
||||
|
||||
def write_step_in_my_code(self, thread_id):
|
||||
self.write("%s\t%s\t%s" % (CMD_STEP_INTO_MY_CODE, self.next_seq(), thread_id,))
|
||||
|
||||
def write_step_return(self, thread_id):
|
||||
self.write("%s\t%s\t%s" % (CMD_STEP_RETURN, self.next_seq(), thread_id,))
|
||||
|
||||
def write_step_return_my_code(self, thread_id):
|
||||
self.write("%s\t%s\t%s" % (CMD_STEP_RETURN_MY_CODE, self.next_seq(), thread_id,))
|
||||
|
||||
def write_step_over_my_code(self, thread_id):
|
||||
self.write("%s\t%s\t%s" % (CMD_STEP_OVER_MY_CODE, self.next_seq(), thread_id,))
|
||||
|
||||
def write_suspend_thread(self, thread_id):
|
||||
self.write("%s\t%s\t%s" % (CMD_THREAD_SUSPEND, self.next_seq(), thread_id,))
|
||||
|
||||
|
|
@ -1094,7 +1113,7 @@ def _get_debugger_test_file(filename):
|
|||
|
||||
ret = os.path.normcase(rPath(os.path.join(os.path.dirname(__file__), filename)))
|
||||
if not os.path.exists(ret):
|
||||
ret = os.path.join(os.path.dirname(ret), 'resources', os.path.basename(ret))
|
||||
ret = os.path.join(os.path.dirname(__file__), 'resources', filename)
|
||||
if not os.path.exists(ret):
|
||||
raise AssertionError('Expected: %s to exist.' % (ret,))
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
if __name__ == '__main__':
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
from not_my_code import other
|
||||
|
||||
def callback2():
|
||||
return 'my code2'
|
||||
|
||||
def callback1():
|
||||
other.call_me_back2(callback2) # first step into my code
|
||||
|
||||
other.call_me_back1(callback1) # break here
|
||||
print('TEST SUCEEDED!')
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
def call_me_back2(callback):
|
||||
a = 'other'
|
||||
callback()
|
||||
return a
|
||||
|
||||
|
||||
def call_me_back1(callback):
|
||||
a = 'other'
|
||||
callback()
|
||||
return a
|
||||
|
|
@ -16,7 +16,8 @@ from tests_python.debugger_unittest import (CMD_SET_PROPERTY_TRACE, REASON_CAUGH
|
|||
CMD_GET_THREAD_STACK, REASON_STEP_INTO_MY_CODE, CMD_GET_EXCEPTION_DETAILS, IS_IRONPYTHON, IS_JYTHON, IS_CPYTHON,
|
||||
IS_APPVEYOR, wait_for_condition, CMD_GET_FRAME, CMD_GET_BREAKPOINT_EXCEPTION,
|
||||
CMD_THREAD_SUSPEND, CMD_STEP_OVER, REASON_STEP_OVER, CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION,
|
||||
CMD_THREAD_RESUME_SINGLE_NOTIFICATION)
|
||||
CMD_THREAD_RESUME_SINGLE_NOTIFICATION, REASON_STEP_RETURN, REASON_STEP_RETURN_MY_CODE,
|
||||
REASON_STEP_OVER_MY_CODE, REASON_STEP_INTO)
|
||||
from _pydevd_bundle.pydevd_constants import IS_WINDOWS
|
||||
try:
|
||||
from urllib import unquote
|
||||
|
|
@ -506,23 +507,37 @@ def test_case_11(case_setup):
|
|||
writer.write_add_breakpoint(2, 'Method1')
|
||||
writer.write_make_initial_run()
|
||||
|
||||
hit = writer.wait_for_breakpoint_hit('111', line=2)
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STOP_ON_BREAKPOINT, line=2)
|
||||
assert hit.name == 'Method1'
|
||||
|
||||
writer.write_step_over(hit.thread_id)
|
||||
|
||||
hit = writer.wait_for_breakpoint_hit('108', line=3)
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, line=3)
|
||||
assert hit.name == 'Method1'
|
||||
|
||||
writer.write_step_over(hit.thread_id)
|
||||
|
||||
hit = writer.wait_for_breakpoint_hit('108', line=11)
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_INTO, line=12) # Reverts to step in
|
||||
assert hit.name == 'Method2'
|
||||
|
||||
writer.write_step_over(hit.thread_id)
|
||||
|
||||
hit = writer.wait_for_breakpoint_hit('108', line=12)
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, line=13)
|
||||
assert hit.name == 'Method2'
|
||||
|
||||
writer.write_run_thread(hit.thread_id)
|
||||
writer.write_step_over(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_INTO, line=18) # Reverts to step in
|
||||
assert hit.name == '<module>'
|
||||
|
||||
assert 13 == writer._sequence, 'Expected 13. Had: %s' % writer._sequence
|
||||
# Finish with a step over
|
||||
writer.write_step_over(hit.thread_id)
|
||||
|
||||
if IS_JYTHON:
|
||||
# Jython got to the exit functions (CPython does it builtin,
|
||||
# so we have no traces from Python).
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_INTO) # Reverts to step in
|
||||
assert hit.name == '_run_exitfuncs'
|
||||
writer.write_run_thread(hit.thread_id)
|
||||
|
||||
writer.finished_ok = True
|
||||
|
||||
|
|
@ -1240,7 +1255,7 @@ def test_unhandled_exceptions_in_top_level2(case_setup_unhandled_exceptions):
|
|||
'_debugger_case_unhandled_exceptions_on_top_level.py',
|
||||
get_environ=get_environ,
|
||||
update_command_line_args=update_command_line_args,
|
||||
EXPECTED_RETURNCODE=(-1, 1, 255), # Python 2.6, Jython can give 255 or -1
|
||||
EXPECTED_RETURNCODE='any',
|
||||
) as writer:
|
||||
|
||||
writer.write_add_exception_breakpoint_with_policy('Exception', "0", "1", "0")
|
||||
|
|
@ -1340,7 +1355,7 @@ def test_unhandled_exceptions_get_stack(case_setup_unhandled_exceptions):
|
|||
|
||||
with case_setup_unhandled_exceptions.test_file(
|
||||
'_debugger_case_unhandled_exception_get_stack.py',
|
||||
EXPECTED_RETURNCODE=(1, 255), # Python 2.6, Jython can give 255
|
||||
EXPECTED_RETURNCODE='any',
|
||||
) as writer:
|
||||
|
||||
writer.write_add_exception_breakpoint_with_policy('Exception', "0", "1", "0")
|
||||
|
|
@ -2368,14 +2383,14 @@ def test_case_single_notification_on_step(case_setup):
|
|||
|
||||
def test_return_value(case_setup):
|
||||
with case_setup.test_file('_debugger_case_return_value.py') as writer:
|
||||
writer.write_add_breakpoint(writer.get_line_index_with_content('break here'), '')
|
||||
break_line = writer.get_line_index_with_content('break here')
|
||||
writer.write_add_breakpoint(break_line, '')
|
||||
writer.write_show_return_vars()
|
||||
writer.write_make_initial_run()
|
||||
hit = writer.wait_for_breakpoint_hit(name='<module>', line=break_line)
|
||||
|
||||
hit = writer.wait_for_breakpoint_hit()
|
||||
writer.write_step_over(hit.thread_id)
|
||||
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER)
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, name='<module>', line=break_line + 1)
|
||||
writer.write_get_frame(hit.thread_id, hit.frame_id)
|
||||
|
||||
writer.wait_for_vars([
|
||||
|
|
@ -2384,6 +2399,17 @@ def test_return_value(case_setup):
|
|||
'<var name="method1" type="int" value="int%253A 1" isRetVal="True"',
|
||||
],
|
||||
])
|
||||
|
||||
writer.write_step_over(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(REASON_STEP_OVER, name='<module>', line=break_line + 2)
|
||||
writer.write_get_frame(hit.thread_id, hit.frame_id)
|
||||
writer.wait_for_vars([
|
||||
[
|
||||
'<var name="method2" type="int" qualifier="%s" value="int: 2" isRetVal="True"' % (builtin_qualifier,),
|
||||
'<var name="method2" type="int" value="int%253A 2" isRetVal="True"',
|
||||
],
|
||||
])
|
||||
|
||||
writer.write_run_thread(hit.thread_id)
|
||||
writer.finished_ok = True
|
||||
|
||||
|
|
@ -2566,6 +2592,64 @@ def test_frame_eval_limitations(case_setup, filename, break_at_lines):
|
|||
|
||||
writer.finished_ok = True
|
||||
|
||||
|
||||
def test_step_return_my_code(case_setup):
|
||||
with case_setup.test_file('my_code/my_code.py') as writer:
|
||||
writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')])
|
||||
writer.write_add_breakpoint(writer.get_line_index_with_content('break here'))
|
||||
writer.write_make_initial_run()
|
||||
hit = writer.wait_for_breakpoint_hit()
|
||||
|
||||
writer.write_step_in_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO_MY_CODE)
|
||||
assert hit.name == 'callback1'
|
||||
|
||||
writer.write_step_in_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO_MY_CODE)
|
||||
assert hit.name == 'callback2'
|
||||
|
||||
writer.write_step_return_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_RETURN_MY_CODE)
|
||||
assert hit.name == 'callback1'
|
||||
|
||||
writer.write_step_return_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_RETURN_MY_CODE)
|
||||
assert hit.name == '<module>'
|
||||
|
||||
writer.write_step_return_my_code(hit.thread_id)
|
||||
writer.finished_ok = True
|
||||
|
||||
|
||||
def test_step_over_my_code(case_setup):
|
||||
with case_setup.test_file('my_code/my_code.py') as writer:
|
||||
writer.write_set_project_roots([debugger_unittest._get_debugger_test_file('my_code')])
|
||||
writer.write_add_breakpoint(writer.get_line_index_with_content('break here'))
|
||||
writer.write_make_initial_run()
|
||||
hit = writer.wait_for_breakpoint_hit()
|
||||
|
||||
writer.write_step_in_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO_MY_CODE)
|
||||
assert hit.name == 'callback1'
|
||||
|
||||
writer.write_step_in_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO_MY_CODE)
|
||||
assert hit.name == 'callback2'
|
||||
|
||||
writer.write_step_over_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO_MY_CODE) # Note: goes from step over to step into
|
||||
assert hit.name == 'callback1'
|
||||
|
||||
writer.write_step_over_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_INTO_MY_CODE) # Note: goes from step over to step into
|
||||
assert hit.name == '<module>'
|
||||
|
||||
writer.write_step_over_my_code(hit.thread_id)
|
||||
hit = writer.wait_for_breakpoint_hit(reason=REASON_STEP_OVER_MY_CODE)
|
||||
assert hit.name == '<module>'
|
||||
|
||||
writer.write_step_over_my_code(hit.thread_id)
|
||||
writer.finished_ok = True
|
||||
|
||||
# Jython needs some vars to be set locally.
|
||||
# set JAVA_HOME=c:\bin\jdk1.8.0_172
|
||||
# set PATH=%PATH%;C:\bin\jython2.7.0\bin
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ WAIT_FOR_THREAD_FINISH_TIMEOUT = 1 # seconds
|
|||
|
||||
STEP_REASONS = {
|
||||
pydevd_comm.CMD_STEP_INTO,
|
||||
pydevd_comm.CMD_STEP_INTO_MY_CODE,
|
||||
pydevd_comm.CMD_STEP_OVER,
|
||||
pydevd_comm.CMD_STEP_OVER_MY_CODE,
|
||||
pydevd_comm.CMD_STEP_RETURN,
|
||||
pydevd_comm.CMD_STEP_INTO_MY_CODE,
|
||||
}
|
||||
|
|
@ -2183,7 +2185,10 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
def on_next(self, request, args):
|
||||
|
||||
tid = self.thread_map.to_pydevd(int(args['threadId']))
|
||||
self.pydevd_notify(pydevd_comm.CMD_STEP_OVER, tid)
|
||||
if self._is_just_my_code_stepping_enabled():
|
||||
self.pydevd_notify(pydevd_comm.CMD_STEP_OVER_MY_CODE, tid)
|
||||
else:
|
||||
self.pydevd_notify(pydevd_comm.CMD_STEP_OVER, tid)
|
||||
self.send_response(request)
|
||||
|
||||
@async_handler
|
||||
|
|
@ -2200,7 +2205,10 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
def on_stepOut(self, request, args):
|
||||
|
||||
tid = self.thread_map.to_pydevd(int(args['threadId']))
|
||||
self.pydevd_notify(pydevd_comm.CMD_STEP_RETURN, tid)
|
||||
if self._is_just_my_code_stepping_enabled():
|
||||
self.pydevd_notify(pydevd_comm.CMD_STEP_RETURN_MY_CODE, tid)
|
||||
else:
|
||||
self.pydevd_notify(pydevd_comm.CMD_STEP_RETURN, tid)
|
||||
self.send_response(request)
|
||||
|
||||
def _get_hit_condition_expression(self, hit_condition):
|
||||
|
|
@ -2546,22 +2554,7 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
@pydevd_events.handler(pydevd_comm.CMD_THREAD_SUSPEND)
|
||||
@async_handler
|
||||
def on_pydevd_thread_suspend(self, seq, args):
|
||||
# TODO: docstring
|
||||
xml = self.parse_xml_response(args)
|
||||
pyd_tid = xml.thread['id']
|
||||
reason = int(xml.thread['stop_reason'])
|
||||
|
||||
# This is needed till https://github.com/Microsoft/ptvsd/issues/477
|
||||
# is done. Remove this after adding the appropriate pydevd commands to
|
||||
# do step over and step out
|
||||
xframes = list(xml.thread.frame)
|
||||
xframe = xframes[0]
|
||||
filepath = unquote_xml_path(xframe['file'])
|
||||
if reason in STEP_REASONS or reason in EXCEPTION_REASONS:
|
||||
if self.internals_filter.is_internal_path(filepath) or \
|
||||
not self._should_debug(filepath):
|
||||
self.pydevd_notify(pydevd_comm.CMD_THREAD_RUN, pyd_tid)
|
||||
return
|
||||
pass
|
||||
|
||||
@pydevd_events.handler(pydevd_comm_constants.CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION)
|
||||
@async_handler
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue