Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioz committed Nov 15, 2023
1 parent 85dbc12 commit c093837
Show file tree
Hide file tree
Showing 9 changed files with 15,935 additions and 15,005 deletions.
29,754 changes: 15,310 additions & 14,444 deletions _pydevd_bundle/pydevd_cython.c

Large diffs are not rendered by default.

523 changes: 258 additions & 265 deletions _pydevd_bundle/pydevd_cython.pyx

Large diffs are not rendered by default.

523 changes: 258 additions & 265 deletions _pydevd_bundle/pydevd_frame.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion _pydevd_bundle/pydevd_trace_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def suspend(plugin, pydb, thread, frame):
return None


def exception_break(plugin, pydb, pydb_frame, frame, args, arg):
def exception_break(plugin, pydb, frame, thread, arg):
return None


Expand Down
71 changes: 52 additions & 19 deletions _pydevd_sys_monitoring/pydevd_sys_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ def get_func_code_info(code_obj) -> FuncCodeInfo:
# func_code_info.filtered_out = False

if not func_code_info.always_skip_code:
# Handle regular breakpoints
breakpoints: dict = py_db.breakpoints.get(func_code_info.canonical_normalized_filename)
function_breakpoint: object = py_db.function_breakpoint_name_to_breakpoint.get(func_code_info.co_name)
# print('\n---')
Expand Down Expand Up @@ -449,6 +450,9 @@ def _raise_event(code, instruction, exc):
unhandled only if it gets into a pydevd. If it's a thread, if it stops
inside the threading and if it's an unmanaged thread (i.e.: QThread)
then stop if it doesn't have a back frame.
Note: unlike other events, this one is global and not per-code (so,
it cannot be individually enabled/disabled for a given code object).
'''
thread_info = _get_thread_info(True, 1)
if thread_info is None:
Expand Down Expand Up @@ -783,23 +787,7 @@ def start_monitoring(all_threads=False):
DEBUGGER_ID = monitor.DEBUGGER_ID
if not monitor.get_tool(DEBUGGER_ID):
monitor.use_tool_id(DEBUGGER_ID, 'pydevd')
monitor.set_events(DEBUGGER_ID, monitor.events.PY_START | monitor.events.PY_RESUME)

monitor.register_callback(DEBUGGER_ID, monitor.events.PY_START, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, _line_event)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RETURN, _return_event)
monitor.register_callback(DEBUGGER_ID, monitor.events.RAISE, _raise_event)

# monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, self._line_callback)
#
# monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RETURN, self._return_callback)
#
# monitor.register_callback(DEBUGGER_ID, monitor.events.RAISE, self._raise_callback)

# Activate exception raise callback if exception breakpoints are registered.
# current_events = monitor.get_events(DEBUGGER_ID)
# monitor.set_events(DEBUGGER_ID, current_events | monitor.events.RAISE)
restart_events(breakpoints_changed=True)
else:
try:
thread_info = _thread_local_info.thread_info
Expand Down Expand Up @@ -835,9 +823,54 @@ def stop_monitoring(all_threads=False):
thread_info.trace = False


def restart_events():
print('restart events')
def restart_events(breakpoints_changed: bool=False) -> None:
print('restart events, breakpoints_changed=', breakpoints_changed)
sys.monitoring.restart_events()
if breakpoints_changed:
# When breakpoints change we need to update what we want to track based
# on the breakpoints.
py_db = GlobalDebuggerHolder.global_dbg
if py_db is None:
return

required_events = 0

has_exception_breakpoint_in_pydb = (
py_db.break_on_caught_exceptions
or py_db.break_on_user_uncaught_exceptions
or py_db.has_plugin_exception_breaks)

if has_exception_breakpoint_in_pydb:
required_events |= monitor.events.RAISE
print('track RAISE')
monitor.register_callback(DEBUGGER_ID, monitor.events.RAISE, _raise_event)
else:
monitor.register_callback(DEBUGGER_ID, monitor.events.RAISE, None)

has_line_breaks = py_db.has_plugin_line_breaks

if not has_line_breaks:
file_to_line_to_breakpoints = py_db.breakpoints
for line_to_breakpoints in file_to_line_to_breakpoints.values():
if line_to_breakpoints:
has_line_breaks = True
break

if has_line_breaks:
print('track PY_START|PY_RESUME')
required_events |= monitor.events.PY_START | monitor.events.PY_RESUME

monitor.register_callback(DEBUGGER_ID, monitor.events.PY_START, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, _line_event)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RETURN, _return_event)
else:
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_START, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, _line_event)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RETURN, _return_event)

monitor.set_events(DEBUGGER_ID, required_events)


def _is_same_frame(info, target_frame, current_frame):
Expand Down
6 changes: 3 additions & 3 deletions pydevd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1171,9 +1171,9 @@ def on_breakpoints_changed(self, removed=False):
if not removed:
# When removing breakpoints we can leave tracing as was, but if a breakpoint was added
# we have to reset the tracing for the existing functions to be re-evaluated.
self.set_tracing_for_untraced_contexts()
self.set_tracing_for_untraced_contexts(breakpoints_changed=True)

def set_tracing_for_untraced_contexts(self):
def set_tracing_for_untraced_contexts(self, breakpoints_changed=False):
# Enable the tracing for existing threads (because there may be frames being executed that
# are currently untraced).

Expand Down Expand Up @@ -1213,7 +1213,7 @@ def set_tracing_for_untraced_contexts(self):
additional_info = None

if USE_SYS_MONITORING:
pydevd_sys_monitoring.restart_events()
pydevd_sys_monitoring.restart_events(breakpoints_changed=breakpoints_changed)

@property
def multi_threads_single_notification(self):
Expand Down
4 changes: 1 addition & 3 deletions pydevd_plugins/django_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,7 @@ def _get_original_filename_from_origin_in_parent_frame_locals(frame, parent_fram
return filename


def exception_break(plugin, main_debugger, pydb_frame, frame, args, arg):
main_debugger = args[0]
thread = args[3]
def exception_break(plugin, main_debugger, frame, thread, arg):
exception, value, trace = arg

if main_debugger.django_exception_break and exception is not None:
Expand Down
6 changes: 2 additions & 4 deletions pydevd_plugins/jinja2_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,9 +469,7 @@ def suspend(plugin, pydb, thread, frame, bp_type):
return None


def exception_break(plugin, pydb, pydb_frame, frame, args, arg):
pydb = args[0]
thread = args[3]
def exception_break(plugin, pydb, frame, thread, arg):
exception, value, trace = arg
if pydb.jinja2_exception_break and exception is not None:
exception_type = list(pydb.jinja2_exception_break.keys())[0]
Expand All @@ -498,7 +496,7 @@ def exception_break(plugin, pydb, pydb_frame, frame, args, arg):

if module_name.startswith('jinja2.'):
# 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)
Expand Down
51 changes: 50 additions & 1 deletion tests_python/test_sys_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def _disable_monitoring():
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, None)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, None)
monitor.register_callback(DEBUGGER_ID, monitor.events.RAISE, None)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RETURN, None)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_UNWIND, None)
sys.monitoring.free_tool_id(DEBUGGER_ID)


Expand Down Expand Up @@ -69,6 +71,54 @@ def method():
]


def test_exceptions_and_return(with_monitoring):
monitor.set_events(DEBUGGER_ID, monitor.events.RAISE | monitor.events.PY_RETURN | monitor.events.PY_UNWIND)

found = []

def _on_raise(code, instruction_offset, exc):
if code.co_filename.endswith('sys_monitoring.py'):
found.append(('raise', code.co_name, str(exc), sys._getframe(1).f_lineno))

def _on_return(code, instruction_offset, val):
if code.co_filename.endswith('sys_monitoring.py'):
found.append(('return', code.co_name, str(val), sys._getframe(1).f_lineno))

def _on_unwind(code, instruction_offset, val):
if code.co_filename.endswith('sys_monitoring.py'):
found.append(('unwind', code.co_name, str(val), sys._getframe(1).f_lineno))

monitor.register_callback(DEBUGGER_ID, monitor.events.RAISE , _on_raise)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RETURN , _on_return)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_UNWIND , _on_unwind)

def method_raise():
raise RuntimeError('err1')

def method_2():
try:
method_raise()
except:
raise

def method():
try:
method_2()
except:
pass

method()

assert found == [
('raise', 'method_raise', 'err1', 96),
('unwind', 'method_raise', 'err1', 96),
('raise', 'method_2', 'err1', 100),
('unwind', 'method_2', 'err1', 102), # This will be helpful for unhandled exceptions!
('raise', 'method', 'err1', 106),
('return', 'method', 'None', 108),
]


def test_variables_on_call(with_monitoring):
monitor.set_events(DEBUGGER_ID, monitor.events.PY_START)

Expand Down Expand Up @@ -147,7 +197,6 @@ def _on_line(code, line):
do_change_line[0] += 1
if do_change_line[0] == 2:
frame = sys._getframe(1)
print(frame.f_lineno)
frame.f_lineno = line - 2

monitor.set_events(DEBUGGER_ID, monitor.events.PY_START | monitor.events.PY_RESUME)
Expand Down

0 comments on commit c093837

Please sign in to comment.