From b826f57dbb8493091b00882cb3143b5cf56d5089 Mon Sep 17 00:00:00 2001 From: Fabio Zadrozny Date: Fri, 16 Jul 2021 09:38:33 -0300 Subject: [PATCH] Fix issue with step into target with `LOAD_METHOD`. Fixes #661 --- .../_pydevd_bundle/pydevd_bytecode_utils.py | 9 +++-- .../pydevd/_pydevd_bundle/pydevd_cython.c | 20 +++++++---- .../pydevd_frame_evaluator.c | 20 +++++++---- .../pydevd/tests_python/test_debugger_json.py | 10 ++++-- .../test_smart_step_into_bytecode.py | 34 ++++++++++++++++--- 5 files changed, 69 insertions(+), 24 deletions(-) diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py index c47686974..e90d7c62c 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_bytecode_utils.py @@ -274,8 +274,7 @@ def on_BINARY_SUBSCR(self, instr): on_BINARY_XOR = on_BINARY_SUBSCR def on_LOAD_METHOD(self, instr): - # ceval sets the top and pushes an additional... the - # final result is simply one additional instruction. + self.on_POP_TOP(instr) # Remove the previous as we're loading something from it. self._stack.append(instr) def on_MAKE_FUNCTION(self, instr): @@ -688,7 +687,11 @@ def _get_smart_step_into_targets(code): pydev_log.exception('Exception computing step into targets (handled).') ret.extend(stack.function_calls) - ret.extend(stack.load_attrs.values()) + # No longer considering attr loads as calls (while in theory sometimes it's possible + # that something as `some.attr` can turn out to be a property which could be stepped + # in, it's not that common in practice and can be surprising for users, so, disabling + # step into from stepping into properties). + # ret.extend(stack.load_attrs.values()) return ret diff --git a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c index 35108ecdb..d90ba5e6e 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c +++ b/src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c @@ -1,4 +1,4 @@ -/* Generated by Cython 0.29.23 */ +/* Generated by Cython 0.29.24 */ /* BEGIN: Cython Metadata { @@ -27,8 +27,8 @@ END: Cython Metadata */ #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else -#define CYTHON_ABI "0_29_23" -#define CYTHON_HEX_VERSION 0x001D17F0 +#define CYTHON_ABI "0_29_24" +#define CYTHON_HEX_VERSION 0x001D18F0 #define CYTHON_FUTURE_DIVISION 0 #include #ifndef offsetof @@ -446,8 +446,12 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) @@ -456,7 +460,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) #endif @@ -36992,11 +37000,9 @@ if (!__Pyx_RefNanny) { #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS PyEval_InitThreads(); #endif - #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; @@ -38428,7 +38434,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; - ternaryfunc call = func->ob_type->tp_call; + ternaryfunc call = Py_TYPE(func)->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) diff --git a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.c b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.c index 7d2e7d9f1..1de9e69e6 100644 --- a/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.c +++ b/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.c @@ -1,4 +1,4 @@ -/* Generated by Cython 0.29.23 */ +/* Generated by Cython 0.29.24 */ /* BEGIN: Cython Metadata { @@ -32,8 +32,8 @@ END: Cython Metadata */ #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) #error Cython requires Python 2.6+ or Python 3.3+. #else -#define CYTHON_ABI "0_29_23" -#define CYTHON_HEX_VERSION 0x001D17F0 +#define CYTHON_ABI "0_29_24" +#define CYTHON_HEX_VERSION 0x001D18F0 #define CYTHON_FUTURE_DIVISION 0 #include #ifndef offsetof @@ -451,8 +451,12 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) @@ -461,7 +465,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif #else #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) #endif @@ -16431,11 +16439,9 @@ if (!__Pyx_RefNanny) { #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS PyEval_InitThreads(); #endif - #endif /*--- Module creation code ---*/ #if CYTHON_PEP489_MULTI_PHASE_INIT __pyx_m = __pyx_pyinit_module; @@ -17238,7 +17244,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, #if CYTHON_COMPILING_IN_CPYTHON static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; - ternaryfunc call = func->ob_type->tp_call; + ternaryfunc call = Py_TYPE(func)->tp_call; if (unlikely(!call)) return PyObject_Call(func, arg, kw); if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py b/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py index 32dbfb001..3e7ccf112 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py +++ b/src/debugpy/_vendored/pydevd/tests_python/test_debugger_json.py @@ -123,13 +123,15 @@ def write_list_threads(self): def wait_for_terminated(self): return self.wait_for_json_message(TerminatedEvent) - def wait_for_thread_stopped(self, reason='breakpoint', line=None, file=None, name=None): + def wait_for_thread_stopped(self, reason='breakpoint', line=None, file=None, name=None, preserve_focus_hint=None): ''' :param file: utf-8 bytes encoded file or unicode ''' stopped_event = self.wait_for_json_message(StoppedEvent) assert stopped_event.body.reason == reason + if preserve_focus_hint is not None: + assert stopped_event.body.preserveFocusHint == preserve_focus_hint json_hit = self.get_stack_as_json_hit(stopped_event.body.threadId) if file is not None: path = json_hit.stack_trace_response.body.stackFrames[0]['source']['path'] @@ -5572,7 +5574,8 @@ def do_something(): # break here json_facade.write_set_function_breakpoints(['do_something']) json_facade.write_make_initial_run() - hit = json_facade.wait_for_thread_stopped('function breakpoint', line=bp) + json_facade.wait_for_thread_stopped( + 'function breakpoint', line=bp, preserve_focus_hint=False) json_facade.write_continue() writer.finished_ok = True @@ -5588,7 +5591,8 @@ def test_function_breakpoints_async(case_setup): json_facade.write_set_function_breakpoints(['gen']) json_facade.write_make_initial_run() - hit = json_facade.wait_for_thread_stopped('function breakpoint', line=bp) + json_facade.wait_for_thread_stopped( + 'function breakpoint', line=bp, preserve_focus_hint=False) json_facade.write_continue() writer.finished_ok = True diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py b/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py index 55ba9887f..48924c527 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py +++ b/src/debugpy/_vendored/pydevd/tests_python/test_smart_step_into_bytecode.py @@ -122,7 +122,7 @@ def function(): found = collect_smart_step_into_variants( frame, 0, 99999, base=function.__code__.co_firstlineno) - check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('yyy', 3), ('call', 5)]) + check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) def test_smart_step_into_bytecode_info_003(): @@ -140,7 +140,7 @@ def function(): found = collect_smart_step_into_variants( frame, 0, 99999, base=function.__code__.co_firstlineno) - check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('yyy', 3), ('call', 5)]) + check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) def test_smart_step_into_bytecode_info_004(): @@ -158,7 +158,7 @@ def function(): found = collect_smart_step_into_variants( frame, 0, 99999, base=function.__code__.co_firstlineno) - check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('yyy', 3), ('call', 5)]) + check_name_and_line(found, [('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) def test_smart_step_into_bytecode_info_005(): @@ -177,7 +177,7 @@ def function(): frame, 0, 99999, base=function.__code__.co_firstlineno) check_name_and_line(found, [ - ('_getframe', 1), ('bar', 2), ('Something', 3), ('yyy', 3), ('call', 5)]) + ('_getframe', 1), ('bar', 2), ('Something', 3), ('call', 5)]) def test_smart_step_into_bytecode_info_006(): @@ -993,6 +993,32 @@ async def function(): ''', [('lock', 1), ('foo', 2)]) +def test_smart_step_into_bytecode_info_056(): + check_names_from_func_str(''' +def function(mask_path): + wc = some_func( + parsed_content, + np.array( + Image.open(mask_path) + ) + ) + +''', [('some_func', 1), ('array', 3), ('open', 4)]) + + +def test_smart_step_into_bytecode_info_057(): + check_names_from_func_str(''' +def function(mask_path): + wc = some_func( + parsed_content, + np.array( + my.pack.Image.open(mask_path) + ) + ) + +''', [('some_func', 1), ('array', 3), ('open', 4)]) + + def test_get_smart_step_into_variant_from_frame_offset(): from _pydevd_bundle.pydevd_bytecode_utils import Variant