Improvements to step into target. Fixes #576

This commit is contained in:
Fabio Zadrozny 2021-05-21 14:36:19 -03:00
parent cbed5de015
commit ab4b9691b7
2 changed files with 423 additions and 49 deletions

View file

@ -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.

View file

@ -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