Skip to content

Commit

Permalink
Use code object instead of (co_firstlineno, co_name, co_filename) for…
Browse files Browse the repository at this point in the history
… caching frame info. Fixes microsoft#837 Fixes microsoft#844
  • Loading branch information
fabioz committed Feb 24, 2022
1 parent ecb43b9 commit 362ace7
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 389 deletions.
6 changes: 6 additions & 0 deletions src/Untitled.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 5
}
685 changes: 306 additions & 379 deletions src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ cdef class PyDBFrame:
cdef str curr_func_name;
cdef bint exist_result;
cdef dict frame_skips_cache;
cdef tuple frame_cache_key;
cdef object frame_cache_key;
cdef tuple line_cache_key;
cdef int breakpoints_in_line_cache;
cdef int breakpoints_in_frame_cache;
Expand Down Expand Up @@ -1640,7 +1640,7 @@ cdef class ThreadTracer:
cdef str filename;
cdef str base;
cdef int pydev_step_cmd;
cdef tuple frame_cache_key;
cdef object frame_cache_key;
cdef dict cache_skips;
cdef bint is_stepping;
cdef tuple abs_path_canonical_path_and_base;
Expand All @@ -1667,7 +1667,7 @@ cdef class ThreadTracer:

# Note: it's important that the context name is also given because we may hit something once
# in the global context and another in the local context.
frame_cache_key = (frame.f_code.co_firstlineno, frame.f_code.co_name, frame.f_code.co_filename)
frame_cache_key = frame.f_code
if frame_cache_key in cache_skips:
if not is_stepping:
# if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name)
Expand All @@ -1681,7 +1681,7 @@ cdef class ThreadTracer:

back_frame = frame.f_back
if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160):
back_frame_cache_key = (back_frame.f_code.co_firstlineno, back_frame.f_code.co_name, back_frame.f_code.co_filename)
back_frame_cache_key = back_frame.f_code
if cache_skips.get(back_frame_cache_key) == 1:
# if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name)
return None if event == 'call' else NO_FTRACE
Expand Down Expand Up @@ -1721,7 +1721,7 @@ cdef class ThreadTracer:
back_frame = frame.f_back
if back_frame is not None and pydev_step_cmd in (107, 144, 109, 160):
if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False):
back_frame_cache_key = (back_frame.f_code.co_firstlineno, back_frame.f_code.co_name, back_frame.f_code.co_filename)
back_frame_cache_key = back_frame.f_code
cache_skips[back_frame_cache_key] = 1
# if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name)
return None if event == 'call' else NO_FTRACE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ def _get_unfiltered_back_frame(self, main_debugger, frame):
# cdef str curr_func_name;
# cdef bint exist_result;
# cdef dict frame_skips_cache;
# cdef tuple frame_cache_key;
# cdef object frame_cache_key;
# cdef tuple line_cache_key;
# cdef int breakpoints_in_line_cache;
# cdef int breakpoints_in_frame_cache;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ def __call__(self, frame, event, arg):
# cdef str filename;
# cdef str base;
# cdef int pydev_step_cmd;
# cdef tuple frame_cache_key;
# cdef object frame_cache_key;
# cdef dict cache_skips;
# cdef bint is_stepping;
# cdef tuple abs_path_canonical_path_and_base;
Expand All @@ -367,7 +367,7 @@ def __call__(self, frame, event, arg):

# Note: it's important that the context name is also given because we may hit something once
# in the global context and another in the local context.
frame_cache_key = (frame.f_code.co_firstlineno, frame.f_code.co_name, frame.f_code.co_filename)
frame_cache_key = frame.f_code
if frame_cache_key in cache_skips:
if not is_stepping:
# if DEBUG: print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name)
Expand All @@ -381,7 +381,7 @@ def __call__(self, frame, event, arg):

back_frame = frame.f_back
if back_frame is not None and pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE):
back_frame_cache_key = (back_frame.f_code.co_firstlineno, back_frame.f_code.co_name, back_frame.f_code.co_filename)
back_frame_cache_key = back_frame.f_code
if cache_skips.get(back_frame_cache_key) == 1:
# if DEBUG: print('skipped: trace_dispatch (cache hit: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name)
return None if event == 'call' else NO_FTRACE
Expand Down Expand Up @@ -421,7 +421,7 @@ def __call__(self, frame, event, arg):
back_frame = frame.f_back
if back_frame is not None and pydev_step_cmd in (CMD_STEP_INTO, CMD_STEP_INTO_MY_CODE, CMD_STEP_RETURN, CMD_STEP_RETURN_MY_CODE):
if py_db.apply_files_filter(back_frame, back_frame.f_code.co_filename, False):
back_frame_cache_key = (back_frame.f_code.co_firstlineno, back_frame.f_code.co_name, back_frame.f_code.co_filename)
back_frame_cache_key = back_frame.f_code
cache_skips[back_frame_cache_key] = 1
# if DEBUG: print('skipped: trace_dispatch (filtered out: 1)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name)
return None if event == 'call' else NO_FTRACE
Expand Down
29 changes: 29 additions & 0 deletions src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -5988,6 +5988,35 @@ def pandas_mod():
writer.finished_ok = True


def test_same_lineno_and_filename(case_setup, pyfile):

@pyfile
def target():

def some_code():
print('1') # Break here

code_obj = compile('''
func()
''', __file__, 'exec')

code_obj = code_obj.replace(co_name=some_code.__code__.co_name, co_firstlineno=some_code.__code__.co_firstlineno)
exec(code_obj, {'func': some_code})

print('TEST SUCEEDED')

with case_setup.test_file(target) as writer:
json_facade = JsonFacade(writer)

writer.write_add_breakpoint(writer.get_line_index_with_content('Break here'))
json_facade.write_launch(justMyCode=False)
json_facade.write_make_initial_run()

json_hit = json_facade.wait_for_thread_stopped()
json_facade.write_continue()
writer.finished_ok = True


if __name__ == '__main__':
pytest.main(['-k', 'test_case_skipping_filters', '-s'])

0 comments on commit 362ace7

Please sign in to comment.