-
-
Couldn't load subscription status.
- Fork 132
Updates to sys.monitoring to get debugpy tests to pass #290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
6da7d9f
02c1825
6a12743
dfa917e
9d57c97
45bd5e9
d87ccff
46e6092
895c855
f39c6ca
06edbb3
202499c
c23b513
3778455
7f808d4
597018b
3c9f6fa
a906bcc
2665bca
00defa9
e29f955
4e4ee8f
873321b
75bdfdf
e13e2cb
83f9bc5
0ee463b
83d21c5
faecb6b
b9b2626
2cdcb7d
36e11f0
d0e781e
c484988
f933c81
7590236
872a0d5
ff3e742
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| RETURN_VALUES_DICT, | ||
| PYTHON_SUSPEND, | ||
| ) | ||
| from _pydevd_bundle.pydevd_frame_utils import short_tb, flag_as_unwinding, short_frame | ||
rchiodo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| from pydevd_file_utils import ( | ||
| NORM_PATHS_AND_BASE_CONTAINER, | ||
| get_abs_path_real_path_and_base_from_file, | ||
|
|
@@ -168,51 +169,67 @@ def _get_bootstrap_frame(depth: int) -> Tuple[Optional[FrameType], bool]: | |
|
|
||
| return f_bootstrap, is_bootstrap_frame_internal | ||
|
|
||
|
|
||
| # fmt: off | ||
| # IFDEF CYTHON | ||
| # cdef _get_unhandled_exception_frame(int depth): | ||
| # cdef _is_user_frame(frame: FrameType): | ||
| # ELSE | ||
| def _get_unhandled_exception_frame(depth: int) -> Optional[FrameType]: | ||
| def _is_user_frame(frame: FrameType) -> bool: | ||
| # ENDIF | ||
| # fmt: on | ||
| try: | ||
| return _thread_local_info.f_unhandled | ||
| except: | ||
| frame = _getframe(depth) | ||
| f_unhandled = frame | ||
| if frame is None: | ||
| return False | ||
|
|
||
| while f_unhandled is not None and f_unhandled.f_back is not None: | ||
| f_back = f_unhandled.f_back | ||
| filename = f_back.f_code.co_filename | ||
| name = splitext(basename(filename))[0] | ||
| filename = frame.f_code.co_filename | ||
| name = splitext(basename(filename))[0] | ||
|
|
||
| # When the back frame is the bootstrap (or if we have no back | ||
| # frame) then use this frame as the one to track. | ||
| if name == "threading": | ||
| if f_back.f_code.co_name in ("__bootstrap", "_bootstrap", "__bootstrap_inner", "_bootstrap_inner", "run"): | ||
| break | ||
| # When the frame is the bootstrap it is not a user frame. | ||
| if name == "threading": | ||
| if frame.f_code.co_name in ("__bootstrap", "_bootstrap", "__bootstrap_inner", "_bootstrap_inner", "run"): | ||
| return False | ||
|
|
||
| elif name == "pydev_monkey": | ||
| if f_back.f_code.co_name == "__call__": | ||
| break | ||
| elif name == "pydev_monkey": | ||
| if frame.f_code.co_name == "__call__": | ||
| return False | ||
|
|
||
| elif name == "pydevd": | ||
| if f_back.f_code.co_name in ("_exec", "run", "main"): | ||
| break | ||
| elif name == "pydevd": | ||
| if frame.f_code.co_name in ("_exec", "run", "main"): | ||
| return False | ||
|
|
||
| elif name == "pydevd_runpy": | ||
| if f_back.f_code.co_name.startswith(("run", "_run")): | ||
| break | ||
| elif name == "pydevd_runpy": | ||
| if frame.f_code.co_name.startswith(("run", "_run")): | ||
| return False | ||
|
|
||
| f_unhandled = f_back | ||
| elif filename == "<frozen runpy>": | ||
| if frame.f_code.co_name.startswith(("run", "_run")): | ||
| return False | ||
|
|
||
| if f_unhandled is not None: | ||
| _thread_local_info.f_unhandled = f_unhandled | ||
| return _thread_local_info.f_unhandled | ||
| elif name == 'runpy': | ||
| if frame.f_code.co_name.startswith(("run", "_run")): | ||
| return False | ||
|
|
||
| return f_unhandled | ||
| return True | ||
|
|
||
| # fmt: off | ||
| # IFDEF CYTHON | ||
| # cdef _is_last_user_frame(frame: FrameType): | ||
| # ELSE | ||
| def _is_last_user_frame(frame: FrameType) -> bool: | ||
|
||
| # ENDIF | ||
| # fmt: on | ||
| # If this frame is not a user frame, then it can't be the last one | ||
| if not _is_user_frame(frame): | ||
| return False | ||
|
|
||
| # If this frame is the last frame, then it is the last one | ||
| if frame.f_back is None: | ||
| return True | ||
|
|
||
| # If the next frame is not a user frame, then this frame is the last one | ||
| if not _is_user_frame(frame.f_back): | ||
| return True | ||
|
|
||
| # Otherwise if the next frame is a user frame, then this frame is not the last one | ||
| return False | ||
|
|
||
| # fmt: off | ||
| # IFDEF CYTHON | ||
|
|
@@ -631,6 +648,7 @@ def _enable_line_tracing(code): | |
| # ENDIF | ||
| # fmt: on | ||
| # print('enable line tracing', code) | ||
| _ensure_monitoring() | ||
| events = monitor.get_local_events(DEBUGGER_ID, code) | ||
| monitor.set_local_events(DEBUGGER_ID, code, events | monitor.events.LINE | monitor.events.JUMP) | ||
|
|
||
|
|
@@ -643,6 +661,7 @@ def _enable_return_tracing(code): | |
| # ENDIF | ||
| # fmt: on | ||
| # print('enable return tracing', code) | ||
| _ensure_monitoring() | ||
rchiodo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| events = monitor.get_local_events(DEBUGGER_ID, code) | ||
| monitor.set_local_events(DEBUGGER_ID, code, events | monitor.events.PY_RETURN) | ||
|
|
||
|
|
@@ -654,6 +673,7 @@ def _enable_return_tracing(code): | |
| def disable_code_tracing(code): | ||
| # ENDIF | ||
| # fmt: on | ||
| _ensure_monitoring() | ||
| monitor.set_local_events(DEBUGGER_ID, code, 0) | ||
|
|
||
|
|
||
|
|
@@ -810,6 +830,9 @@ def _unwind_event(code, instruction, exc): | |
| if thread_info is None: | ||
| return | ||
|
|
||
| frame = _getframe(1) | ||
rchiodo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| arg = (type(exc), exc, exc.__traceback__) | ||
|
|
||
| py_db: object = GlobalDebuggerHolder.global_dbg | ||
| if py_db is None or py_db.pydb_disposed: | ||
| return | ||
|
|
@@ -818,19 +841,18 @@ def _unwind_event(code, instruction, exc): | |
| # For thread-related stuff we can't disable the code tracing because other | ||
| # threads may still want it... | ||
| return | ||
|
|
||
| func_code_info: FuncCodeInfo = _get_func_code_info(code, 1) | ||
| if func_code_info.always_skip_code: | ||
| return | ||
|
|
||
| # print('_unwind_event', code, exc) | ||
| frame = _getframe(1) | ||
| arg = (type(exc), exc, exc.__traceback__) | ||
|
|
||
| has_caught_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_caught_exception_breakpoint_in_pydb: | ||
| _should_stop, frame, user_uncaught_exc_info = should_stop_on_exception( | ||
| py_db, thread_info.additional_info, frame, thread_info.thread, arg, None | ||
|
|
@@ -842,18 +864,18 @@ def _unwind_event(code, instruction, exc): | |
| container_obj = _TryExceptContainerObj(py_db.collect_try_except_info(frame.f_code)) | ||
| func_code_info.try_except_container_obj = container_obj | ||
|
|
||
| if is_unhandled_exception( | ||
| is_unhandled = is_unhandled_exception( | ||
| func_code_info.try_except_container_obj, py_db, frame, user_uncaught_exc_info[1], user_uncaught_exc_info[2] | ||
| ): | ||
| ) | ||
|
|
||
| if is_unhandled: | ||
| # print('stop in user uncaught') | ||
| handle_exception(py_db, thread_info.thread, frame, user_uncaught_exc_info[0], EXCEPTION_TYPE_USER_UNHANDLED) | ||
| return | ||
|
|
||
| break_on_uncaught_exceptions = py_db.break_on_uncaught_exceptions | ||
| if break_on_uncaught_exceptions: | ||
| if frame is _get_unhandled_exception_frame(depth=1): | ||
| stop_on_unhandled_exception(py_db, thread_info.thread, thread_info.additional_info, arg) | ||
| return | ||
| if break_on_uncaught_exceptions and _is_last_user_frame(frame): | ||
| stop_on_unhandled_exception(py_db, thread_info.thread, thread_info.additional_info, arg) | ||
|
|
||
|
|
||
| # fmt: off | ||
|
|
@@ -882,6 +904,9 @@ def _raise_event(code, instruction, exc): | |
| if thread_info is None: | ||
| return | ||
|
|
||
| frame = _getframe(1) | ||
rchiodo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| arg = (type(exc), exc, exc.__traceback__) | ||
|
|
||
| py_db: object = GlobalDebuggerHolder.global_dbg | ||
| if py_db is None or py_db.pydb_disposed: | ||
| return | ||
|
|
@@ -897,15 +922,23 @@ def _raise_event(code, instruction, exc): | |
|
|
||
| # print('_raise_event --- ', code, exc) | ||
|
|
||
| frame = _getframe(1) | ||
| arg = (type(exc), exc, exc.__traceback__) | ||
| # Compute the previous exception info (if any). We use it to check if the exception | ||
| # should be stopped | ||
| prev_exc_info = _thread_local_info._user_uncaught_exc_info if hasattr(_thread_local_info, "_user_uncaught_exc_info") else None | ||
| should_stop, frame, _user_uncaught_exc_info = should_stop_on_exception( | ||
| py_db, thread_info.additional_info, frame, thread_info.thread, arg, None | ||
| py_db, thread_info.additional_info, frame, thread_info.thread, arg, prev_exc_info | ||
| ) | ||
|
|
||
| # Save the current exception info for the next raise event. | ||
| _thread_local_info._user_uncaught_exc_info = _user_uncaught_exc_info | ||
|
|
||
| # print('!!!! should_stop (in raise)', should_stop) | ||
| if should_stop: | ||
| handle_exception(py_db, thread_info.thread, frame, arg, EXCEPTION_TYPE_HANDLED) | ||
| return | ||
|
|
||
| # Once we leave the raise event, we are no longer in the state of 'just_raised', so | ||
| # indicate that this traceback is for an exception in the unwinding state | ||
| flag_as_unwinding(exc.__traceback__) | ||
fabioz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| # fmt: off | ||
|
|
@@ -1333,6 +1366,10 @@ def _jump_event(code, from_offset, to_offset): | |
|
|
||
| # We know the frame depth. | ||
| frame = _getframe(1) | ||
|
|
||
| # Disable the next line event as we're jumping to a line. The line event will be redundant. | ||
fabioz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| _thread_local_info.f_disable_next_line_if_match = frame.f_lineno | ||
|
|
||
| return _internal_line_event(func_code_info, frame, frame.f_lineno) | ||
|
|
||
|
|
||
|
|
@@ -1364,6 +1401,14 @@ def _line_event(code, line): | |
| # For thread-related stuff we can't disable the code tracing because other | ||
| # threads may still want it... | ||
| return | ||
|
|
||
| if hasattr(_thread_local_info, "f_disable_next_line_if_match"): | ||
| if _thread_local_info.f_disable_next_line_if_match is line: | ||
| # If we're in a jump, we should skip this line event. The jump would have | ||
| # been considered a line event for this same line and we don't want to | ||
| # stop twice. | ||
| del _thread_local_info.f_disable_next_line_if_match | ||
| return | ||
|
|
||
| func_code_info: FuncCodeInfo = _get_func_code_info(code, 1) | ||
| if func_code_info.always_skip_code or func_code_info.always_filtered_out: | ||
|
|
@@ -1604,6 +1649,7 @@ def _start_method_event(code, instruction_offset): | |
| # threads may still want it... | ||
| return | ||
|
|
||
|
|
||
| frame = _getframe(1) | ||
| func_code_info = _get_func_code_info(code, frame) | ||
| if func_code_info.always_skip_code: | ||
|
|
@@ -1651,6 +1697,19 @@ def _start_method_event(code, instruction_offset): | |
|
|
||
| return monitor.DISABLE | ||
|
|
||
| # fmt: off | ||
| # IFDEF CYTHON | ||
| # cpdef _ensure_monitoring(): | ||
| # ELSE | ||
| def _ensure_monitoring(): | ||
| # ENDIF | ||
| # fmt: on | ||
| DEBUGGER_ID = monitor.DEBUGGER_ID | ||
| if not monitor.get_tool(DEBUGGER_ID): | ||
| monitor.use_tool_id(DEBUGGER_ID, "pydevd") | ||
| update_monitor_events() | ||
| restart_events() | ||
|
|
||
|
|
||
| # fmt: off | ||
| # IFDEF CYTHON | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.