Skip to content

Commit

Permalink
Starting to add support for Python 3.11. WIP microsoft#939
Browse files Browse the repository at this point in the history
Added support for setting tracing to different threads
along with some general fixes.

Main things missing:
- Compile with cython extensions
- Bytecode manipulation
- Frame eval mode (requires bytecode manipulation)
  • Loading branch information
fabioz committed Jun 24, 2022
1 parent e94b719 commit c6f7efd
Show file tree
Hide file tree
Showing 36 changed files with 1,591 additions and 1,007 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def parse_cmdline(argv=None):
elif opt in ("-c", "--config_file"):
config_file = value.strip()
if os.path.exists(config_file):
f = open(config_file, 'rU')
f = open(config_file, 'r')
try:
config_file_contents = f.read()
finally:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import dis
import opcode as _opcode

from _pydevd_bundle.pydevd_constants import KeyifyList, DebugInfoHolder
from _pydevd_bundle.pydevd_constants import KeyifyList, DebugInfoHolder, IS_PY311_OR_GREATER
from bisect import bisect
from collections import deque

Expand Down Expand Up @@ -125,6 +125,8 @@ def _getcallname(self, instr):
if instr.name == 'LOAD_ASSERTION_ERROR':
return 'AssertionError'
name = self._getname(instr)
if isinstance(name, CodeType):
name = name.co_qualname # Note: only available for Python 3.11
if isinstance(name, _Variable):
name = name.name

Expand Down Expand Up @@ -279,8 +281,14 @@ def on_LOAD_METHOD(self, instr):
self._stack.append(instr)

def on_MAKE_FUNCTION(self, instr):
qualname = self._stack.pop()
code_obj_instr = self._stack.pop()
if not IS_PY311_OR_GREATER:
# The qualifier name is no longer put in the stack.
qualname = self._stack.pop()
code_obj_instr = self._stack.pop()
else:
# In 3.11 the code object has a co_qualname which we can use.
qualname = code_obj_instr = self._stack.pop()

arg = instr.arg
if arg & 0x08:
_func_closure = self._stack.pop()
Expand Down Expand Up @@ -313,6 +321,9 @@ def on_CALL_METHOD(self, instr):
func_name_instr = self._stack.pop()
self._handle_call_from_instr(func_name_instr, instr)

def on_PUSH_NULL(self, instr):
self._stack.append(instr)

def on_CALL_FUNCTION(self, instr):
arg = instr.arg

Expand Down Expand Up @@ -523,6 +534,12 @@ def on_BUILD_CONST_KEY_MAP(self, instr):
on_GET_AWAITABLE = _no_stack_change
on_GET_YIELD_FROM_ITER = _no_stack_change

def on_RETURN_GENERATOR(self, instr):
self._stack.append(instr)

on_RETURN_GENERATOR = _no_stack_change
on_RESUME = _no_stack_change

def on_MAP_ADD(self, instr):
self.on_POP_TOP(instr)
self.on_POP_TOP(instr)
Expand Down Expand Up @@ -650,6 +667,9 @@ def on_DELETE_SUBSCR(self, instr):
on_UNARY_NOT = _no_stack_change
on_UNARY_INVERT = _no_stack_change

on_CACHE = _no_stack_change
on_PRECALL = _no_stack_change


def _get_smart_step_into_targets(code):
'''
Expand All @@ -668,17 +688,20 @@ def _get_smart_step_into_targets(code):
try:
func_name = 'on_%s' % (instr.name,)
func = getattr(stack, func_name, None)

if DEBUG:
if instr.name != 'CACHE': # Filter the ones we don't want to see.
print('\nWill handle: ', instr, '>>', stack._getname(instr), '<<')
print('Current stack:')
for entry in stack._stack:
print(' arg:', stack._getname(entry), '(', entry, ')')

if func is None:
if STRICT_MODE:
raise AssertionError('%s not found.' % (func_name,))
else:
continue
if DEBUG:
print('\nWill handle: ', instr, '>>', stack._getname(instr), '<<')
func(instr)
if DEBUG:
for entry in stack._stack:
print(' arg:', stack._getname(entry), '(', entry, ')')
except:
if STRICT_MODE:
raise # Error in strict mode.
Expand Down Expand Up @@ -784,7 +807,11 @@ def calculate_smart_step_into_variants(frame, start_line, end_line, base=0):

call_order_cache = {}
if DEBUG:
dis.dis(code)
print('dis.dis:')
if IS_PY311_OR_GREATER:
dis.dis(code, show_caches=False)
else:
dis.dis(code)

for target in _get_smart_step_into_targets(code):
variant = _convert_target_to_variant(target, start_line, end_line, call_order_cache, lasti, base)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ def collect_try_except_info(co, use_func_first_line=False):

return try_except_info_lst

if sys.version_info[:2] >= (3, 10):
elif sys.version_info[:2] == (3, 10):

class _TargetInfo(object):

Expand Down Expand Up @@ -460,6 +460,16 @@ def collect_try_except_info(co, use_func_first_line=False):

return try_except_info_lst

elif sys.version_info[:2] >= (3, 11):

def collect_try_except_info(co, use_func_first_line=False):
'''
Note: if the filename is available and we can get the source,
`collect_try_except_info_from_source` is preferred (this is kept as
a fallback for cases where sources aren't available).
'''
return []

import ast as ast_module


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ def _current_frames():
IS_PY38_OR_GREATER = sys.version_info >= (3, 8)
IS_PY39_OR_GREATER = sys.version_info >= (3, 9)
IS_PY310_OR_GREATER = sys.version_info >= (3, 10)
IS_PY311_OR_GREATER = sys.version_info >= (3, 11)


def version_str(v):
Expand Down
Loading

0 comments on commit c6f7efd

Please sign in to comment.