mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Improvements to step into target. Fixes #576
This commit is contained in:
parent
cbed5de015
commit
ab4b9691b7
2 changed files with 423 additions and 49 deletions
|
|
@ -5,11 +5,12 @@ Note: not importable from Python 2.
|
|||
"""
|
||||
|
||||
import sys
|
||||
from _pydev_bundle import pydev_log
|
||||
if sys.version_info[0] < 3:
|
||||
raise ImportError('This module is only compatible with Python 3.')
|
||||
|
||||
from _pydev_bundle import pydev_log
|
||||
from types import CodeType
|
||||
from _pydevd_frame_eval.vendored.bytecode.instr import _Variable
|
||||
from _pydevd_frame_eval.vendored import bytecode
|
||||
from _pydevd_frame_eval.vendored.bytecode import cfg as bytecode_cfg
|
||||
import dis
|
||||
|
|
@ -118,10 +119,19 @@ class _StackInterpreter(object):
|
|||
if instr.name == 'BINARY_SUBSCR':
|
||||
return '__getitem__().__call__'
|
||||
if instr.name == 'CALL_FUNCTION':
|
||||
return '__call__().__call__'
|
||||
# Note: previously a '__call__().__call__' was returned, but this was a bit weird
|
||||
# and on Python 3.9 this construct could appear for some internal things where
|
||||
# it wouldn't be expected.
|
||||
# Note: it'd be what we had in func()().
|
||||
return None
|
||||
if instr.name == 'MAKE_FUNCTION':
|
||||
return '__func__().__call__'
|
||||
if instr.name == 'LOAD_ASSERTION_ERROR':
|
||||
return 'AssertionError'
|
||||
name = self._getname(instr)
|
||||
if isinstance(name, _Variable):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
return None
|
||||
if name.endswith('>'): # xxx.<listcomp>, xxx.<lambda>, ...
|
||||
|
|
@ -134,8 +144,14 @@ class _StackInterpreter(object):
|
|||
def on_LOAD_GLOBAL(self, instr):
|
||||
self._stack.append(instr)
|
||||
|
||||
def on_POP_TOP(self, instr):
|
||||
try:
|
||||
self._stack.pop()
|
||||
except IndexError:
|
||||
pass # Ok (in the end of blocks)
|
||||
|
||||
def on_LOAD_ATTR(self, instr):
|
||||
self._stack.pop() # replaces the current top
|
||||
self.on_POP_TOP(instr) # replaces the current top
|
||||
self._stack.append(instr)
|
||||
self.load_attrs[_TargetIdHashable(instr)] = Target(self._getname(instr), instr.lineno, instr.offset)
|
||||
|
||||
|
|
@ -144,6 +160,18 @@ class _StackInterpreter(object):
|
|||
def on_LOAD_CONST(self, instr):
|
||||
self._stack.append(instr)
|
||||
|
||||
on_LOAD_DEREF = on_LOAD_CONST
|
||||
on_LOAD_NAME = on_LOAD_CONST
|
||||
on_LOAD_CLOSURE = on_LOAD_CONST
|
||||
on_LOAD_CLASSDEREF = on_LOAD_CONST
|
||||
|
||||
# Although it actually changes the stack, it's inconsequential for us as a function call can't
|
||||
# really be found there.
|
||||
on_IMPORT_NAME = _no_stack_change
|
||||
on_IMPORT_FROM = _no_stack_change
|
||||
on_IMPORT_STAR = _no_stack_change
|
||||
on_SETUP_ANNOTATIONS = _no_stack_change
|
||||
|
||||
def on_STORE_FAST(self, instr):
|
||||
try:
|
||||
self._stack.pop()
|
||||
|
|
@ -152,9 +180,24 @@ class _StackInterpreter(object):
|
|||
|
||||
# Note: it stores in the locals and doesn't put anything in the stack.
|
||||
|
||||
on_STORE_GLOBAL = on_STORE_FAST
|
||||
on_STORE_DEREF = on_STORE_FAST
|
||||
on_STORE_ATTR = on_STORE_FAST
|
||||
on_STORE_NAME = on_STORE_FAST
|
||||
|
||||
on_DELETE_NAME = on_POP_TOP
|
||||
on_DELETE_ATTR = on_POP_TOP
|
||||
on_DELETE_GLOBAL = on_POP_TOP
|
||||
on_DELETE_FAST = on_POP_TOP
|
||||
on_DELETE_DEREF = on_POP_TOP
|
||||
|
||||
on_DICT_UPDATE = on_POP_TOP
|
||||
on_SET_UPDATE = on_POP_TOP
|
||||
|
||||
def _handle_call_from_instr(self, func_name_instr, func_call_instr):
|
||||
self.load_attrs.pop(_TargetIdHashable(func_name_instr), None)
|
||||
call_name = self._getcallname(func_name_instr)
|
||||
target = None
|
||||
if not call_name:
|
||||
pass # Ignore if we can't identify a name
|
||||
elif call_name in ('<listcomp>', '<genexpr>', '<setcomp>', '<dictcomp>'):
|
||||
|
|
@ -165,12 +208,17 @@ class _StackInterpreter(object):
|
|||
# i.e.: we have targets inside of a <listcomp> or <genexpr>.
|
||||
# Note that to actually match this in the debugger we need to do matches on 2 frames,
|
||||
# the one with the <listcomp> and then the actual target inside the <listcomp>.
|
||||
target = Target(call_name, func_name_instr.lineno, func_call_instr.offset, children_targets)
|
||||
self.function_calls.append(
|
||||
Target(call_name, func_name_instr.lineno, func_call_instr.offset, children_targets))
|
||||
target)
|
||||
|
||||
else:
|
||||
# Ok, regular call
|
||||
self.function_calls.append(Target(call_name, func_name_instr.lineno, func_call_instr.offset))
|
||||
target = Target(call_name, func_name_instr.lineno, func_call_instr.offset)
|
||||
self.function_calls.append(target)
|
||||
|
||||
if DEBUG and target is not None:
|
||||
print('Created target', target)
|
||||
self._stack.append(func_call_instr) # Keep the func call as the result
|
||||
|
||||
def on_COMPARE_OP(self, instr):
|
||||
|
|
@ -252,6 +300,9 @@ class _StackInterpreter(object):
|
|||
def on_LOAD_FAST(self, instr):
|
||||
self._stack.append(instr)
|
||||
|
||||
def on_LOAD_ASSERTION_ERROR(self, instr):
|
||||
self._stack.append(instr)
|
||||
|
||||
on_LOAD_BUILD_CLASS = on_LOAD_FAST
|
||||
|
||||
def on_CALL_METHOD(self, instr):
|
||||
|
|
@ -286,7 +337,28 @@ class _StackInterpreter(object):
|
|||
_names_of_kw_args = self._stack.pop()
|
||||
|
||||
# pop the actual args
|
||||
for _ in range(instr.arg):
|
||||
arg = instr.arg
|
||||
|
||||
argc = arg & 0xff # positional args
|
||||
argc += ((arg >> 8) * 2) # keyword args
|
||||
|
||||
for _ in range(argc):
|
||||
self._stack.pop()
|
||||
|
||||
func_name_instr = self._stack.pop()
|
||||
self._handle_call_from_instr(func_name_instr, instr)
|
||||
|
||||
def on_CALL_FUNCTION_VAR(self, instr):
|
||||
# var name
|
||||
_var_arg = self._stack.pop()
|
||||
|
||||
# pop the actual args
|
||||
arg = instr.arg
|
||||
|
||||
argc = arg & 0xff # positional args
|
||||
argc += ((arg >> 8) * 2) # keyword args
|
||||
|
||||
for _ in range(argc):
|
||||
self._stack.pop()
|
||||
|
||||
func_name_instr = self._stack.pop()
|
||||
|
|
@ -319,12 +391,20 @@ class _StackInterpreter(object):
|
|||
self._handle_call_from_instr(func_name_instr, instr)
|
||||
|
||||
on_YIELD_VALUE = _no_stack_change
|
||||
on_GET_AITER = _no_stack_change
|
||||
on_GET_ANEXT = _no_stack_change
|
||||
on_END_ASYNC_FOR = _no_stack_change
|
||||
on_BEFORE_ASYNC_WITH = _no_stack_change
|
||||
on_SETUP_ASYNC_WITH = _no_stack_change
|
||||
on_YIELD_FROM = _no_stack_change
|
||||
on_SETUP_LOOP = _no_stack_change
|
||||
on_FOR_ITER = _no_stack_change
|
||||
on_BREAK_LOOP = _no_stack_change
|
||||
on_JUMP_ABSOLUTE = _no_stack_change
|
||||
on_RERAISE = _no_stack_change
|
||||
on_LIST_TO_TUPLE = _no_stack_change
|
||||
on_CALL_FINALLY = _no_stack_change
|
||||
on_POP_FINALLY = _no_stack_change
|
||||
|
||||
def on_JUMP_IF_FALSE_OR_POP(self, instr):
|
||||
try:
|
||||
|
|
@ -414,12 +494,6 @@ class _StackInterpreter(object):
|
|||
self._stack.append(p2)
|
||||
self._stack.append(p3)
|
||||
|
||||
def on_POP_TOP(self, instr):
|
||||
try:
|
||||
self._stack.pop()
|
||||
except IndexError:
|
||||
pass # Ok (in the end of blocks)
|
||||
|
||||
def on_BUILD_LIST_FROM_ARG(self, instr):
|
||||
self._stack.append(instr)
|
||||
|
||||
|
|
@ -442,9 +516,12 @@ class _StackInterpreter(object):
|
|||
on_LIST_APPEND = on_POP_TOP
|
||||
on_SET_ADD = on_POP_TOP
|
||||
on_LIST_EXTEND = on_POP_TOP
|
||||
on_UNPACK_EX = on_POP_TOP
|
||||
|
||||
# ok: doesn't change the stack (converts top to getiter(top))
|
||||
on_GET_ITER = _no_stack_change
|
||||
on_GET_AWAITABLE = _no_stack_change
|
||||
on_GET_YIELD_FROM_ITER = _no_stack_change
|
||||
|
||||
def on_MAP_ADD(self, instr):
|
||||
self.on_POP_TOP(instr)
|
||||
|
|
@ -461,13 +538,19 @@ class _StackInterpreter(object):
|
|||
self._stack.append(instr)
|
||||
|
||||
on_BUILD_TUPLE = on_BUILD_LIST
|
||||
on_BUILD_STRING = on_BUILD_LIST
|
||||
on_BUILD_TUPLE_UNPACK_WITH_CALL = on_BUILD_LIST
|
||||
on_BUILD_TUPLE_UNPACK = on_BUILD_LIST
|
||||
on_BUILD_LIST_UNPACK = on_BUILD_LIST
|
||||
on_BUILD_MAP_UNPACK_WITH_CALL = on_BUILD_LIST
|
||||
on_BUILD_MAP_UNPACK = on_BUILD_LIST
|
||||
on_BUILD_SET = on_BUILD_LIST
|
||||
on_BUILD_SET_UNPACK = on_BUILD_LIST
|
||||
|
||||
on_SETUP_FINALLY = _no_stack_change
|
||||
on_POP_FINALLY = _no_stack_change
|
||||
on_BEGIN_FINALLY = _no_stack_change
|
||||
on_END_FINALLY = _no_stack_change
|
||||
|
||||
def on_RAISE_VARARGS(self, instr):
|
||||
for _i in range(instr.arg):
|
||||
|
|
@ -484,6 +567,8 @@ class _StackInterpreter(object):
|
|||
on_SETUP_WITH = _no_stack_change
|
||||
on_WITH_CLEANUP_START = _no_stack_change
|
||||
on_WITH_CLEANUP_FINISH = _no_stack_change
|
||||
on_FORMAT_VALUE = _no_stack_change
|
||||
on_EXTENDED_ARG = _no_stack_change
|
||||
|
||||
def on_INPLACE_ADD(self, instr):
|
||||
# This would actually pop 2 and leave the value in the stack.
|
||||
|
|
|
|||
|
|
@ -36,6 +36,35 @@ def check(found, expected):
|
|||
last_offset = f.offset
|
||||
|
||||
|
||||
def collect_smart_step_into_variants(*args, **kwargs):
|
||||
try:
|
||||
return pydevd_bytecode_utils.calculate_smart_step_into_variants(*args, **kwargs)
|
||||
except:
|
||||
# In a failure, rerun with DEBUG!
|
||||
debug = pydevd_bytecode_utils.DEBUG
|
||||
pydevd_bytecode_utils.DEBUG = True
|
||||
try:
|
||||
return pydevd_bytecode_utils.calculate_smart_step_into_variants(*args, **kwargs)
|
||||
finally:
|
||||
pydevd_bytecode_utils.DEBUG = debug
|
||||
|
||||
|
||||
def check_names_from_func_str(func_str, expected):
|
||||
locs = {}
|
||||
exec(func_str, globals(), locs)
|
||||
|
||||
function = locs['function']
|
||||
|
||||
class Frame:
|
||||
f_code = function.__code__
|
||||
f_lasti = 0
|
||||
|
||||
found = collect_smart_step_into_variants(
|
||||
Frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, expected)
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info():
|
||||
from _pydevd_bundle.pydevd_bytecode_utils import Variant
|
||||
|
||||
|
|
@ -53,7 +82,7 @@ def test_smart_step_into_bytecode_info():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check(found, [
|
||||
|
|
@ -90,7 +119,7 @@ def test_smart_step_into_bytecode_info_002():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
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)])
|
||||
|
|
@ -108,7 +137,7 @@ def test_smart_step_into_bytecode_info_003():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
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)])
|
||||
|
|
@ -126,7 +155,7 @@ def test_smart_step_into_bytecode_info_004():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
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)])
|
||||
|
|
@ -144,7 +173,7 @@ def test_smart_step_into_bytecode_info_005():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [
|
||||
|
|
@ -170,7 +199,7 @@ def test_smart_step_into_bytecode_info_006():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [
|
||||
|
|
@ -186,7 +215,7 @@ def test_smart_step_into_bytecode_info_007():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('__getitem__', 2)])
|
||||
|
|
@ -202,7 +231,7 @@ def test_smart_step_into_bytecode_info_008():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 2)])
|
||||
|
|
@ -217,7 +246,7 @@ def test_smart_step_into_bytecode_info_009():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('__getitem__', 2), ('__getitem__().__call__', 2)])
|
||||
|
|
@ -232,10 +261,10 @@ def test_smart_step_into_bytecode_info_011():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('__getitem__', 2), ('__getitem__().__call__', 2), ('__call__().__call__', 2)])
|
||||
check_name_and_line(found, [('_getframe', 1), ('__getitem__', 2), ('__getitem__().__call__', 2)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_012():
|
||||
|
|
@ -247,7 +276,7 @@ def test_smart_step_into_bytecode_info_012():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('<lambda>', 2)])
|
||||
|
|
@ -262,7 +291,7 @@ def test_smart_step_into_bytecode_info_013():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('__getitem__().__call__', 2), ('__getitem__', 2)])
|
||||
|
|
@ -282,7 +311,7 @@ def test_smart_step_into_bytecode_info_014():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('RuntimeError', 3), ('call2', 5), ('call3', 7)])
|
||||
|
|
@ -298,7 +327,7 @@ def test_smart_step_into_bytecode_info_015():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 2), ('call2', 3)])
|
||||
|
|
@ -319,7 +348,7 @@ def test_smart_step_into_bytecode_info_016():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call2', 2)])
|
||||
|
|
@ -337,7 +366,7 @@ def test_smart_step_into_bytecode_info_017():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found,
|
||||
|
|
@ -360,7 +389,7 @@ def test_smart_step_into_bytecode_info_018():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('Foo', 8)])
|
||||
|
|
@ -381,7 +410,7 @@ def test_smart_step_into_bytecode_info_019():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('Foo', 8)])
|
||||
|
|
@ -406,7 +435,7 @@ def test_smart_step_into_bytecode_info_020():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [
|
||||
|
|
@ -425,7 +454,7 @@ def test_smart_step_into_bytecode_info_021():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('a', 5)])
|
||||
|
|
@ -449,7 +478,7 @@ def test_smart_step_into_bytecode_info_022():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [
|
||||
|
|
@ -474,7 +503,7 @@ def test_smart_step_into_bytecode_info_023():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [
|
||||
|
|
@ -507,7 +536,7 @@ def test_smart_step_into_bytecode_info_024():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [
|
||||
|
|
@ -580,7 +609,7 @@ def test_smart_step_into_bytecode_info_025():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 15)])
|
||||
|
|
@ -600,7 +629,7 @@ def test_smart_step_into_bytecode_info_026():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 2)])
|
||||
|
|
@ -621,7 +650,7 @@ def test_smart_step_into_bytecode_info_027():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('__getitem__', 8), ('__getitem__().__call__', 8)])
|
||||
|
|
@ -642,7 +671,7 @@ def test_smart_step_into_bytecode_info_028():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('__getitem__', 7), ('__getitem__', 8), ('__getitem__().__call__', 8)])
|
||||
|
|
@ -658,7 +687,7 @@ def test_smart_step_into_bytecode_info_029():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('__add__', 3), ('__mul__', 3), ('__sub__', 3), ('call', 3)])
|
||||
|
|
@ -674,7 +703,7 @@ def test_smart_step_into_bytecode_info_030():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 3)])
|
||||
|
|
@ -690,7 +719,7 @@ def test_smart_step_into_bytecode_info_031():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 3)])
|
||||
|
|
@ -707,7 +736,7 @@ def test_smart_step_into_bytecode_info_032():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 4)])
|
||||
|
|
@ -715,18 +744,253 @@ def test_smart_step_into_bytecode_info_032():
|
|||
|
||||
def test_smart_step_into_bytecode_info_033():
|
||||
|
||||
def function():
|
||||
check_names_from_func_str('''def function():
|
||||
yield sys._getframe()
|
||||
|
||||
raise call()
|
||||
''', [('_getframe', 1), ('call', 3)])
|
||||
|
||||
generator = iter(function())
|
||||
|
||||
@pytest.mark.skipif(sys.version_info[0:2] < (3, 6), reason='Async only available for Python 3.6 onwards.')
|
||||
def test_smart_step_into_bytecode_info_034():
|
||||
|
||||
check_names_from_func_str('''async def function():
|
||||
await a()
|
||||
async for b in c():
|
||||
await d()
|
||||
''', [('a', 1), ('c', 2), ('d', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_035():
|
||||
|
||||
check_names_from_func_str('''def function():
|
||||
assert 0, 'Foo'
|
||||
''', [('AssertionError', 1)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_036():
|
||||
|
||||
check_names_from_func_str('''def function(a):
|
||||
global some_name
|
||||
some_name = a
|
||||
some_name()
|
||||
''', [('some_name', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_037():
|
||||
|
||||
func = '''def function():
|
||||
some_name = 10
|
||||
def another():
|
||||
nonlocal some_name
|
||||
some_name = a
|
||||
some_name()
|
||||
return another
|
||||
'''
|
||||
locs = {}
|
||||
exec(func, globals(), locs)
|
||||
|
||||
function = locs['function']()
|
||||
|
||||
class Frame:
|
||||
f_code = function.__code__
|
||||
f_lasti = 0
|
||||
|
||||
found = collect_smart_step_into_variants(
|
||||
Frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('some_name', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_038():
|
||||
check_names_from_func_str('''def function():
|
||||
try:
|
||||
call()
|
||||
finally:
|
||||
call2()
|
||||
''', [('call', 2), ('call2', 4)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_039():
|
||||
check_names_from_func_str('''def function():
|
||||
try:
|
||||
call()
|
||||
except:
|
||||
return call2()
|
||||
finally:
|
||||
return call3()
|
||||
''', [('call', 2), ('call2', 4), ('call3', 6)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_040():
|
||||
check_names_from_func_str('''def function():
|
||||
a.call = foo()
|
||||
a.call()
|
||||
''', [('foo', 1), ('call', 2)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_041():
|
||||
check_names_from_func_str('''def function():
|
||||
foo = 10
|
||||
del foo
|
||||
foo = method
|
||||
foo()
|
||||
''', [('foo', 4)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_042():
|
||||
check_names_from_func_str('''
|
||||
foo = 10
|
||||
def function():
|
||||
global foo
|
||||
foo()
|
||||
''', [('foo', 2)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_043():
|
||||
|
||||
def function(call):
|
||||
|
||||
def another_function():
|
||||
yield sys._getframe()
|
||||
|
||||
call()
|
||||
|
||||
for frame in another_function():
|
||||
yield frame
|
||||
|
||||
generator = iter(function(lambda: None))
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('_getframe', 1), ('call', 3)])
|
||||
check_name_and_line(found, [('_getframe', 3), ('call', 5)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_044():
|
||||
check_names_from_func_str('''
|
||||
def function(args):
|
||||
call, *c = args
|
||||
call(*c)
|
||||
''', [('call', 2)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_045():
|
||||
check_names_from_func_str('''
|
||||
def function():
|
||||
x.foo = 10
|
||||
del x.foo
|
||||
x.foo = lambda:None
|
||||
x.foo()
|
||||
''', [('foo', 4)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_046():
|
||||
check_names_from_func_str('''
|
||||
a = 10
|
||||
def function(args):
|
||||
global a
|
||||
del a
|
||||
a()
|
||||
''', [('a', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_047():
|
||||
check_names_from_func_str('''
|
||||
def function():
|
||||
call(a, b=1, *c, **kw)
|
||||
''', [('call', 1)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_048():
|
||||
check_names_from_func_str('''
|
||||
def function(fn):
|
||||
fn = call(fn)
|
||||
|
||||
def pa():
|
||||
fn()
|
||||
|
||||
return pa()
|
||||
|
||||
''', [('call', 1), ('pa', 6)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_049():
|
||||
|
||||
def function(foo):
|
||||
|
||||
class SomeClass(object):
|
||||
implementation = foo
|
||||
|
||||
implementation()
|
||||
f = sys._getframe()
|
||||
|
||||
return SomeClass.f
|
||||
|
||||
frame = function(object)
|
||||
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
check_name_and_line(found, [('implementation', 5), ('_getframe', 6)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_050():
|
||||
check_names_from_func_str('''
|
||||
def function():
|
||||
('a' 'b').index('x')
|
||||
|
||||
''', [('index', 1)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_051():
|
||||
check_names_from_func_str('''
|
||||
def function():
|
||||
v = 1
|
||||
v2 = 2
|
||||
call((f'a{v()!r}' f'b{v2()}'))
|
||||
|
||||
''', [('call', 3), ('v', 3), ('v2', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_052():
|
||||
check_names_from_func_str('''
|
||||
def function():
|
||||
v = 1
|
||||
v2 = 2
|
||||
call({*v(), *v2()})
|
||||
|
||||
''', [('call', 3), ('v', 3), ('v2', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_053():
|
||||
check_names_from_func_str('''
|
||||
def function():
|
||||
v = 1
|
||||
v2 = 2
|
||||
call({**v(), **v2()})
|
||||
|
||||
''', [('call', 3), ('v', 3), ('v2', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_054():
|
||||
check_names_from_func_str('''
|
||||
def function():
|
||||
import a
|
||||
from a import b
|
||||
call()
|
||||
|
||||
''', [('call', 3)])
|
||||
|
||||
|
||||
def test_smart_step_into_bytecode_info_055():
|
||||
check_names_from_func_str('''
|
||||
async def function():
|
||||
async with lock() as foo:
|
||||
await foo()
|
||||
|
||||
''', [('lock', 1), ('foo', 2)])
|
||||
|
||||
|
||||
def test_get_smart_step_into_variant_from_frame_offset():
|
||||
|
|
@ -778,7 +1042,7 @@ def test_smart_step_into_bytecode_info_00eq():
|
|||
generator = iter(function())
|
||||
frame = next(generator)
|
||||
|
||||
found = pydevd_bytecode_utils.calculate_smart_step_into_variants(
|
||||
found = collect_smart_step_into_variants(
|
||||
frame, 0, 99999, base=function.__code__.co_firstlineno)
|
||||
|
||||
if sys.version_info[:2] < (3, 9):
|
||||
|
|
@ -802,3 +1066,28 @@ def test_smart_step_into_bytecode_info_00eq():
|
|||
Variant(name='__le__', is_visited=True, line=13, offset=93, call_order=1),
|
||||
Variant(name=('_getframe', 'sys'), is_visited=True, line=18, offset=123, call_order=1),
|
||||
])
|
||||
|
||||
|
||||
def _test_find_bytecode():
|
||||
import glob
|
||||
import dis
|
||||
from io import StringIO
|
||||
root_dir = 'C:\\bin\\Miniconda\\envs\\py36_tests\\Lib\\site-packages\\'
|
||||
|
||||
i = 0
|
||||
for filename in glob.iglob(root_dir + '**/*.py', recursive=True):
|
||||
print(filename)
|
||||
with open(filename, 'r', encoding='utf-8') as stream:
|
||||
contents = stream.read()
|
||||
|
||||
code_obj = compile(contents, filename, 'exec')
|
||||
s = StringIO()
|
||||
dis.dis(code_obj, file=s)
|
||||
if 'EXTENDED_ARG' in s.getvalue():
|
||||
dis.dis(code_obj)
|
||||
raise AssertionError('Found bytecode in: %s' % filename)
|
||||
|
||||
# i += 1
|
||||
# if i == 1000:
|
||||
# break
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue