mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Assorted fixes for Python 3.10 support:
Split test/requirements.txt into two different lists, one for py2, and the other for py3; update package versions in py3 list as needed to support py3.10. Fix usage of deprecated threading functions getName(), setName(), isDaemon(), and currentThread(). Refactor test_invalid_breakpoints to be more declarative to handle Python version differences more easily and clearly, and fix it for py3.10. Disable Django tests on py3.10 (#689). Disable gevent tests on py3.10 (#688).
This commit is contained in:
parent
0e5b8f7a7c
commit
3a9f7d64c4
23 changed files with 131 additions and 79 deletions
|
|
@ -559,7 +559,7 @@ class BaseInterpreterInterface:
|
||||||
|
|
||||||
from _pydevd_bundle.pydevd_constants import set_thread_id
|
from _pydevd_bundle.pydevd_constants import set_thread_id
|
||||||
from _pydev_bundle import pydev_localhost
|
from _pydev_bundle import pydev_localhost
|
||||||
set_thread_id(threading.currentThread(), "console_main")
|
set_thread_id(threading.current_thread(), "console_main")
|
||||||
|
|
||||||
VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java
|
VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java
|
||||||
VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java
|
VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java
|
||||||
|
|
|
||||||
|
|
@ -1032,12 +1032,12 @@ class _NewThreadStartupWithTrace:
|
||||||
# Note: if this is a thread from threading.py, we're too early in the boostrap process (because we mocked
|
# Note: if this is a thread from threading.py, we're too early in the boostrap process (because we mocked
|
||||||
# the start_new_thread internal machinery and thread._bootstrap has not finished), so, the code below needs
|
# the start_new_thread internal machinery and thread._bootstrap has not finished), so, the code below needs
|
||||||
# to make sure that we use the current thread bound to the original function and not use
|
# to make sure that we use the current thread bound to the original function and not use
|
||||||
# threading.currentThread() unless we're sure it's a dummy thread.
|
# current_thread() unless we're sure it's a dummy thread.
|
||||||
t = getattr(self.original_func, '__self__', getattr(self.original_func, 'im_self', None))
|
t = getattr(self.original_func, '__self__', getattr(self.original_func, 'im_self', None))
|
||||||
if not isinstance(t, threading.Thread):
|
if not isinstance(t, threading.Thread):
|
||||||
# This is not a threading.Thread but a Dummy thread (so, get it as a dummy thread using
|
# This is not a threading.Thread but a Dummy thread (so, get it as a dummy thread using
|
||||||
# currentThread).
|
# currentThread).
|
||||||
t = threading.currentThread()
|
t = threading.current_thread()
|
||||||
|
|
||||||
if not getattr(t, 'is_pydev_daemon_thread', False):
|
if not getattr(t, 'is_pydev_daemon_thread', False):
|
||||||
thread_id = get_current_thread_id(t)
|
thread_id = get_current_thread_id(t)
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ class ReaderThread(PyDBDaemonThread):
|
||||||
|
|
||||||
self.sock = sock
|
self.sock = sock
|
||||||
self._buffer = b''
|
self._buffer = b''
|
||||||
self.setName("pydevd.Reader")
|
self.name = "pydevd.Reader"
|
||||||
self.process_net_command = process_net_command
|
self.process_net_command = process_net_command
|
||||||
self.process_net_command_json = PyDevJsonCommandProcessor(self._from_json).process_net_command_json
|
self.process_net_command_json = PyDevJsonCommandProcessor(self._from_json).process_net_command_json
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ class FSNotifyThread(PyDBDaemonThread):
|
||||||
def __init__(self, py_db, api, watch_dirs):
|
def __init__(self, py_db, api, watch_dirs):
|
||||||
PyDBDaemonThread.__init__(self, py_db)
|
PyDBDaemonThread.__init__(self, py_db)
|
||||||
self.api = api
|
self.api = api
|
||||||
self.setName("pydevd.FSNotifyThread")
|
self.name = "pydevd.FSNotifyThread"
|
||||||
self.watcher = fsnotify.Watcher()
|
self.watcher = fsnotify.Watcher()
|
||||||
self.watch_dirs = watch_dirs
|
self.watch_dirs = watch_dirs
|
||||||
|
|
||||||
|
|
@ -359,7 +359,7 @@ class WriterThread(PyDBDaemonThread):
|
||||||
PyDBDaemonThread.__init__(self, py_db)
|
PyDBDaemonThread.__init__(self, py_db)
|
||||||
self.sock = sock
|
self.sock = sock
|
||||||
self.__terminate_on_socket_close = terminate_on_socket_close
|
self.__terminate_on_socket_close = terminate_on_socket_close
|
||||||
self.setName("pydevd.Writer")
|
self.name = "pydevd.Writer"
|
||||||
self._cmd_queue = _queue.Queue()
|
self._cmd_queue = _queue.Queue()
|
||||||
if pydevd_vm_type.get_vm_type() == 'python':
|
if pydevd_vm_type.get_vm_type() == 'python':
|
||||||
self.timeout = 0
|
self.timeout = 0
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ def add_custom_frame(frame, name, thread_id):
|
||||||
Returns the custom thread id which will be used to show the given frame paused.
|
Returns the custom thread id which will be used to show the given frame paused.
|
||||||
'''
|
'''
|
||||||
with CustomFramesContainer.custom_frames_lock:
|
with CustomFramesContainer.custom_frames_lock:
|
||||||
curr_thread_id = get_current_thread_id(threading.currentThread())
|
curr_thread_id = get_current_thread_id(threading.current_thread())
|
||||||
next_id = CustomFramesContainer._next_frame_id = CustomFramesContainer._next_frame_id + 1
|
next_id = CustomFramesContainer._next_frame_id = CustomFramesContainer._next_frame_id + 1
|
||||||
|
|
||||||
# Note: the frame id kept contains an id and thread information on the thread where the frame was added
|
# Note: the frame id kept contains an id and thread information on the thread where the frame was added
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ class PyDBDaemonThread(threading.Thread):
|
||||||
created_pydb_daemon[self] = 1
|
created_pydb_daemon[self] = 1
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
if IS_JYTHON and not isinstance(threading.currentThread(), threading._MainThread):
|
if IS_JYTHON and not isinstance(threading.current_thread(), threading._MainThread):
|
||||||
# we shouldn't update sys.modules for the main thread, cause it leads to the second importing 'threading'
|
# we shouldn't update sys.modules for the main thread, cause it leads to the second importing 'threading'
|
||||||
# module, and the new instance of main thread is created
|
# module, and the new instance of main thread is created
|
||||||
ss = JyCore.PySystemState()
|
ss = JyCore.PySystemState()
|
||||||
|
|
@ -59,7 +59,7 @@ class PyDBDaemonThread(threading.Thread):
|
||||||
|
|
||||||
def do_kill_pydev_thread(self):
|
def do_kill_pydev_thread(self):
|
||||||
if not self._kill_received:
|
if not self._kill_received:
|
||||||
pydev_log.debug('%s received kill signal', self.getName())
|
pydev_log.debug('%s received kill signal', self.name)
|
||||||
self._kill_received = True
|
self._kill_received = True
|
||||||
|
|
||||||
def _stop_trace(self):
|
def _stop_trace(self):
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ class NetCommandFactoryJson(NetCommandFactory):
|
||||||
# Notify that it's created (no-op if we already notified before).
|
# Notify that it's created (no-op if we already notified before).
|
||||||
py_db.notify_thread_created(thread_id, thread)
|
py_db.notify_thread_created(thread_id, thread)
|
||||||
|
|
||||||
thread_schema = pydevd_schema.Thread(id=thread_id, name=thread.getName())
|
thread_schema = pydevd_schema.Thread(id=thread_id, name=thread.name)
|
||||||
threads.append(thread_schema.to_dict())
|
threads.append(thread_schema.to_dict())
|
||||||
|
|
||||||
body = pydevd_schema.ThreadsResponseBody(threads)
|
body = pydevd_schema.ThreadsResponseBody(threads)
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class NetCommandFactory(object):
|
||||||
|
|
||||||
def _thread_to_xml(self, thread):
|
def _thread_to_xml(self, thread):
|
||||||
""" thread information as XML """
|
""" thread information as XML """
|
||||||
name = pydevd_xml.make_valid_xml_value(thread.getName())
|
name = pydevd_xml.make_valid_xml_value(thread.name)
|
||||||
cmdText = '<thread name="%s" id="%s" />' % (quote(name), get_thread_id(thread))
|
cmdText = '<thread name="%s" id="%s" />' % (quote(name), get_thread_id(thread))
|
||||||
return cmdText
|
return cmdText
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -448,4 +448,3 @@ def interrupt_main_thread(main_thread):
|
||||||
main_thread._thread.interrupt() # Jython
|
main_thread._thread.interrupt() # Jython
|
||||||
except:
|
except:
|
||||||
pydev_log.exception('Error on interrupt main thread fallback.')
|
pydev_log.exception('Error on interrupt main thread fallback.')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ def iter_frames(frame):
|
||||||
|
|
||||||
def dump_frames(thread_id):
|
def dump_frames(thread_id):
|
||||||
sys.stdout.write('dumping frames\n')
|
sys.stdout.write('dumping frames\n')
|
||||||
if thread_id != get_current_thread_id(threading.currentThread()):
|
if thread_id != get_current_thread_id(threading.current_thread()):
|
||||||
raise VariableError("find_frame: must execute on same thread")
|
raise VariableError("find_frame: must execute on same thread")
|
||||||
|
|
||||||
frame = get_frame()
|
frame = get_frame()
|
||||||
|
|
@ -65,7 +65,7 @@ def getVariable(dbg, thread_id, frame_id, scope, attrs):
|
||||||
not the frame (as we don't care about the frame in this case).
|
not the frame (as we don't care about the frame in this case).
|
||||||
"""
|
"""
|
||||||
if scope == 'BY_ID':
|
if scope == 'BY_ID':
|
||||||
if thread_id != get_current_thread_id(threading.currentThread()):
|
if thread_id != get_current_thread_id(current_thread()):
|
||||||
raise VariableError("getVariable: must execute on same thread")
|
raise VariableError("getVariable: must execute on same thread")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ def _get_line_for_frame(frame):
|
||||||
def _pydev_stop_at_break(line):
|
def _pydev_stop_at_break(line):
|
||||||
frame = sys._getframe(1)
|
frame = sys._getframe(1)
|
||||||
# print('pydevd SET TRACING at ', line, 'curr line', frame.f_lineno)
|
# print('pydevd SET TRACING at ', line, 'curr line', frame.f_lineno)
|
||||||
t = threading.currentThread()
|
t = threading.current_thread()
|
||||||
try:
|
try:
|
||||||
additional_info = t.additional_info
|
additional_info = t.additional_info
|
||||||
except:
|
except:
|
||||||
|
|
@ -73,7 +73,7 @@ def _pydev_needs_stop_at_break(line):
|
||||||
# then, proceed to go to the current line
|
# then, proceed to go to the current line
|
||||||
# (which will then trigger a line event).
|
# (which will then trigger a line event).
|
||||||
'''
|
'''
|
||||||
t = threading.currentThread()
|
t = threading.current_thread()
|
||||||
try:
|
try:
|
||||||
additional_info = t.additional_info
|
additional_info = t.additional_info
|
||||||
except:
|
except:
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ if __name__ == '__main__':
|
||||||
sys.exit = skip_successful_exit
|
sys.exit = skip_successful_exit
|
||||||
|
|
||||||
connect_status_queue = _queue.Queue()
|
connect_status_queue = _queue.Queue()
|
||||||
interpreter = InterpreterInterface(host, int(client_port), threading.currentThread(), connect_status_queue=connect_status_queue)
|
interpreter = InterpreterInterface(host, int(client_port), threading.current_thread(), connect_status_queue=connect_status_queue)
|
||||||
|
|
||||||
server_thread = threading.Thread(target=start_console_server,
|
server_thread = threading.Thread(target=start_console_server,
|
||||||
name='ServerThread',
|
name='ServerThread',
|
||||||
|
|
|
||||||
|
|
@ -440,7 +440,7 @@ def start_server(host, port, client_port):
|
||||||
# note that this does not work in jython!!! (sys method can't be replaced).
|
# note that this does not work in jython!!! (sys method can't be replaced).
|
||||||
sys.exit = do_exit
|
sys.exit = do_exit
|
||||||
|
|
||||||
interpreter = InterpreterInterface(host, client_port, threading.currentThread())
|
interpreter = InterpreterInterface(host, client_port, threading.current_thread())
|
||||||
|
|
||||||
start_new_thread(start_console_server, (host, port, interpreter))
|
start_new_thread(start_console_server, (host, port, interpreter))
|
||||||
|
|
||||||
|
|
@ -457,7 +457,7 @@ def get_interpreter():
|
||||||
try:
|
try:
|
||||||
interpreterInterface = getattr(__builtin__, 'interpreter')
|
interpreterInterface = getattr(__builtin__, 'interpreter')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
interpreterInterface = InterpreterInterface(None, None, threading.currentThread())
|
interpreterInterface = InterpreterInterface(None, None, threading.current_thread())
|
||||||
__builtin__.interpreter = interpreterInterface
|
__builtin__.interpreter = interpreterInterface
|
||||||
sys.stderr.write(interpreterInterface.get_greeting_msg())
|
sys.stderr.write(interpreterInterface.get_greeting_msg())
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ if SUPPORT_PLUGINS:
|
||||||
from _pydevd_bundle.pydevd_plugin_utils import PluginManager
|
from _pydevd_bundle.pydevd_plugin_utils import PluginManager
|
||||||
|
|
||||||
threadingEnumerate = threading.enumerate
|
threadingEnumerate = threading.enumerate
|
||||||
threadingCurrentThread = threading.currentThread
|
threadingCurrentThread = threading.current_thread
|
||||||
|
|
||||||
try:
|
try:
|
||||||
'dummy'.encode('utf-8') # Added because otherwise Jython 2.2.1 wasn't finding the encoding (if it wasn't loaded in the main thread).
|
'dummy'.encode('utf-8') # Added because otherwise Jython 2.2.1 wasn't finding the encoding (if it wasn't loaded in the main thread).
|
||||||
|
|
@ -179,7 +179,7 @@ class PyDBCommandThread(PyDBDaemonThread):
|
||||||
def __init__(self, py_db):
|
def __init__(self, py_db):
|
||||||
PyDBDaemonThread.__init__(self, py_db)
|
PyDBDaemonThread.__init__(self, py_db)
|
||||||
self._py_db_command_thread_event = py_db._py_db_command_thread_event
|
self._py_db_command_thread_event = py_db._py_db_command_thread_event
|
||||||
self.setName('pydevd.CommandThread')
|
self.name = 'pydevd.CommandThread'
|
||||||
|
|
||||||
@overrides(PyDBDaemonThread._on_run)
|
@overrides(PyDBDaemonThread._on_run)
|
||||||
def _on_run(self):
|
def _on_run(self):
|
||||||
|
|
@ -223,7 +223,7 @@ class CheckAliveThread(PyDBDaemonThread):
|
||||||
|
|
||||||
def __init__(self, py_db):
|
def __init__(self, py_db):
|
||||||
PyDBDaemonThread.__init__(self, py_db)
|
PyDBDaemonThread.__init__(self, py_db)
|
||||||
self.setName('pydevd.CheckAliveThread')
|
self.name = 'pydevd.CheckAliveThread'
|
||||||
self.daemon = False
|
self.daemon = False
|
||||||
self._wait_event = threading.Event()
|
self._wait_event = threading.Event()
|
||||||
|
|
||||||
|
|
@ -1317,7 +1317,7 @@ class PyDB(object):
|
||||||
'Error in debugger: Found PyDBDaemonThread not marked with is_pydev_daemon_thread=True.\n')
|
'Error in debugger: Found PyDBDaemonThread not marked with is_pydev_daemon_thread=True.\n')
|
||||||
|
|
||||||
if is_thread_alive(t):
|
if is_thread_alive(t):
|
||||||
if not t.isDaemon() or hasattr(t, "__pydevd_main_thread"):
|
if not t.daemon or hasattr(t, "__pydevd_main_thread"):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
@ -2159,8 +2159,8 @@ class PyDB(object):
|
||||||
break
|
break
|
||||||
time.sleep(1 / 10.)
|
time.sleep(1 / 10.)
|
||||||
else:
|
else:
|
||||||
thread_names = [t.getName() for t in get_pydb_daemon_threads_to_wait()]
|
thread_names = [t.name for t in get_pydb_daemon_threads_to_wait()]
|
||||||
if thread_names:
|
if thread_names:
|
||||||
pydev_log.debug("The following pydb threads may not have finished correctly: %s",
|
pydev_log.debug("The following pydb threads may not have finished correctly: %s",
|
||||||
', '.join(thread_names))
|
', '.join(thread_names))
|
||||||
finally:
|
finally:
|
||||||
|
|
@ -2345,8 +2345,8 @@ class PyDB(object):
|
||||||
if self.thread_analyser is not None:
|
if self.thread_analyser is not None:
|
||||||
wrap_threads()
|
wrap_threads()
|
||||||
self.thread_analyser.set_start_time(cur_time())
|
self.thread_analyser.set_start_time(cur_time())
|
||||||
send_concurrency_message("threading_event", 0, t.getName(), thread_id, "thread", "start", file, 1, None, parent=thread_id)
|
send_concurrency_message("threading_event", 0, t.name, thread_id, "thread", "start", file, 1, None, parent=thread_id)
|
||||||
|
|
||||||
if self.asyncio_analyser is not None:
|
if self.asyncio_analyser is not None:
|
||||||
# we don't have main thread in asyncio graph, so we should add a fake event
|
# we don't have main thread in asyncio graph, so we should add a fake event
|
||||||
send_concurrency_message("asyncio_event", 0, "Task", "Task", "thread", "stop", file, 1, frame=None, parent=None)
|
send_concurrency_message("asyncio_event", 0, "Task", "Task", "thread", "stop", file, 1, frame=None, parent=None)
|
||||||
|
|
@ -2400,7 +2400,7 @@ class PyDB(object):
|
||||||
def wait_for_commands(self, globals):
|
def wait_for_commands(self, globals):
|
||||||
self._activate_mpl_if_needed()
|
self._activate_mpl_if_needed()
|
||||||
|
|
||||||
thread = threading.currentThread()
|
thread = threading.current_thread()
|
||||||
from _pydevd_bundle import pydevd_frame_utils
|
from _pydevd_bundle import pydevd_frame_utils
|
||||||
frame = pydevd_frame_utils.Frame(None, -1, pydevd_frame_utils.FCode("Console",
|
frame = pydevd_frame_utils.Frame(None, -1, pydevd_frame_utils.FCode("Console",
|
||||||
os.path.abspath(os.path.dirname(__file__))), globals, globals)
|
os.path.abspath(os.path.dirname(__file__))), globals, globals)
|
||||||
|
|
@ -2926,7 +2926,7 @@ class DispatchReader(ReaderThread):
|
||||||
|
|
||||||
@overrides(ReaderThread._on_run)
|
@overrides(ReaderThread._on_run)
|
||||||
def _on_run(self):
|
def _on_run(self):
|
||||||
dummy_thread = threading.currentThread()
|
dummy_thread = threading.current_thread()
|
||||||
dummy_thread.is_pydev_daemon_thread = False
|
dummy_thread.is_pydev_daemon_thread = False
|
||||||
return ReaderThread._on_run(self)
|
return ReaderThread._on_run(self)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ try:
|
||||||
except:
|
except:
|
||||||
from urllib.parse import quote # @UnresolvedImport
|
from urllib.parse import quote # @UnresolvedImport
|
||||||
|
|
||||||
threadingCurrentThread = threading.currentThread
|
threadingCurrentThread = threading.current_thread
|
||||||
|
|
||||||
DONT_TRACE_THREADING = ['threading.py', 'pydevd.py']
|
DONT_TRACE_THREADING = ['threading.py', 'pydevd.py']
|
||||||
INNER_METHODS = ['_stop']
|
INNER_METHODS = ['_stop']
|
||||||
|
|
@ -105,7 +105,7 @@ def send_concurrency_message(event_class, time, name, thread_id, type, event, fi
|
||||||
|
|
||||||
def log_new_thread(global_debugger, t):
|
def log_new_thread(global_debugger, t):
|
||||||
event_time = cur_time() - global_debugger.thread_analyser.start_time
|
event_time = cur_time() - global_debugger.thread_analyser.start_time
|
||||||
send_concurrency_message("threading_event", event_time, t.getName(), get_thread_id(t), "thread",
|
send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "thread",
|
||||||
"start", "code_name", 0, None, parent=get_thread_id(t))
|
"start", "code_name", 0, None, parent=get_thread_id(t))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -162,7 +162,7 @@ class ThreadingLogger:
|
||||||
if not self_obj.is_alive():
|
if not self_obj.is_alive():
|
||||||
return
|
return
|
||||||
thread_id = get_thread_id(t)
|
thread_id = get_thread_id(t)
|
||||||
name = t.getName()
|
name = t.name
|
||||||
self_obj._pydev_join_called = True
|
self_obj._pydev_join_called = True
|
||||||
|
|
||||||
if real_method == "start":
|
if real_method == "start":
|
||||||
|
|
@ -200,7 +200,7 @@ class ThreadingLogger:
|
||||||
# back_back_base is the file, where the method was called froms
|
# back_back_base is the file, where the method was called froms
|
||||||
return
|
return
|
||||||
if method_name == "__init__":
|
if method_name == "__init__":
|
||||||
send_concurrency_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock",
|
send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "lock",
|
||||||
method_name, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(frame.f_locals["self"])))
|
method_name, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(frame.f_locals["self"])))
|
||||||
if "attr" in frame.f_locals and \
|
if "attr" in frame.f_locals and \
|
||||||
(frame.f_locals["attr"] in LOCK_METHODS or
|
(frame.f_locals["attr"] in LOCK_METHODS or
|
||||||
|
|
@ -215,14 +215,14 @@ class ThreadingLogger:
|
||||||
if real_method == "release_end":
|
if real_method == "release_end":
|
||||||
# do not log release end. Maybe use it later
|
# do not log release end. Maybe use it later
|
||||||
return
|
return
|
||||||
send_concurrency_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock",
|
send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "lock",
|
||||||
real_method, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj)))
|
real_method, back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj)))
|
||||||
|
|
||||||
if real_method in ("put_end", "get_end"):
|
if real_method in ("put_end", "get_end"):
|
||||||
# fake release for queue, cause we don't call it directly
|
# fake release for queue, cause we don't call it directly
|
||||||
send_concurrency_message("threading_event", event_time, t.getName(), get_thread_id(t), "lock",
|
send_concurrency_message("threading_event", event_time, t.name, get_thread_id(t), "lock",
|
||||||
"release", back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj)))
|
"release", back.f_code.co_filename, back.f_lineno, back, lock_id=str(id(self_obj)))
|
||||||
# print(event_time, t.getName(), get_thread_id(t), "lock",
|
# print(event_time, t.name, get_thread_id(t), "lock",
|
||||||
# real_method, back.f_code.co_filename, back.f_lineno)
|
# real_method, back.f_code.co_filename, back.f_lineno)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class Test(unittest.TestCase):
|
||||||
time.sleep(.3) # let's give it some time to start the threads
|
time.sleep(.3) # let's give it some time to start the threads
|
||||||
|
|
||||||
from _pydev_bundle import pydev_localhost
|
from _pydev_bundle import pydev_localhost
|
||||||
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.currentThread())
|
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.current_thread())
|
||||||
|
|
||||||
(result,) = interpreter.hello("Hello pydevconsole")
|
(result,) = interpreter.hello("Hello pydevconsole")
|
||||||
self.assertEqual(result, "Hello eclipse")
|
self.assertEqual(result, "Hello eclipse")
|
||||||
|
|
@ -53,7 +53,7 @@ class Test(unittest.TestCase):
|
||||||
from _pydev_bundle import pydev_localhost
|
from _pydev_bundle import pydev_localhost
|
||||||
from _pydev_bundle.pydev_console_utils import CodeFragment
|
from _pydev_bundle.pydev_console_utils import CodeFragment
|
||||||
|
|
||||||
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.currentThread())
|
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.current_thread())
|
||||||
sys.stdout = pydevd_io.IOBuf()
|
sys.stdout = pydevd_io.IOBuf()
|
||||||
interpreter.add_exec(CodeFragment('class Foo:\n CONSTANT=1\n'))
|
interpreter.add_exec(CodeFragment('class Foo:\n CONSTANT=1\n'))
|
||||||
interpreter.add_exec(CodeFragment('foo=Foo()'))
|
interpreter.add_exec(CodeFragment('foo=Foo()'))
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ def get_marked_line_numbers(path):
|
||||||
|
|
||||||
print(1) # @foo
|
print(1) # @foo
|
||||||
print(2)
|
print(2)
|
||||||
print(3) # @bar
|
print(3) # @bar,baz
|
||||||
|
|
||||||
the function will return::
|
the function will return::
|
||||||
|
|
||||||
{"foo": 1, "bar": 3}
|
{"foo": 1, "bar": 3, "baz": 3}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(path, py.path.local):
|
if isinstance(path, py.path.local):
|
||||||
|
|
@ -40,10 +40,11 @@ def get_marked_line_numbers(path):
|
||||||
with open(path, "rb") as f:
|
with open(path, "rb") as f:
|
||||||
lines = {}
|
lines = {}
|
||||||
for i, line in enumerate(f):
|
for i, line in enumerate(f):
|
||||||
match = re.search(br"#\s*@\s*(.+?)\s*$", line)
|
match = re.search(br"#\s*@(.+?)\s*$", line)
|
||||||
if match:
|
if match:
|
||||||
marker = compat.force_unicode(match.group(1), "ascii")
|
markers = compat.force_unicode(match.group(1), "ascii")
|
||||||
lines[marker] = i + 1
|
for marker in markers.split(","):
|
||||||
|
lines[marker] = i + 1
|
||||||
|
|
||||||
_marked_line_numbers_cache[path] = lines
|
_marked_line_numbers_cache[path] = lines
|
||||||
return lines
|
return lines
|
||||||
|
|
|
||||||
|
|
@ -328,46 +328,46 @@ def test_invalid_breakpoints(pyfile, target, run):
|
||||||
|
|
||||||
debuggee.setup()
|
debuggee.setup()
|
||||||
|
|
||||||
|
# For markers below, rN = requested breakpoint, eN = expected breakpoint.
|
||||||
|
# If there's no eN for some rN, it's assumed to be the same line.
|
||||||
# fmt: off
|
# fmt: off
|
||||||
b = True
|
b = True
|
||||||
while b: # @bp1-expected
|
while b: # @e0-27,e0-35,e0-36,e0-37,e0-38,e0-39
|
||||||
pass # @bp1-requested
|
pass # @r0
|
||||||
break
|
break
|
||||||
|
|
||||||
print() # @bp2-expected
|
print() # @e1-27,e1-35,e1-36,e1-37
|
||||||
[ # @bp2-requested
|
[ # @r1,e2
|
||||||
1, 2, 3, # @bp3-expected
|
1, 2, 3, # @e2-27,e2-35,e2-36,e2-37,e2-38
|
||||||
] # @bp3-requested
|
] # @r2
|
||||||
|
|
||||||
# Python 2.7 only.
|
# Python 2.7 only.
|
||||||
print() # @bp4-expected
|
print() # @e3,e4
|
||||||
print(1, # @bp4-requested-1
|
print(1, # @r3
|
||||||
2, 3, # @bp4-requested-2
|
2, 3, # @r4
|
||||||
4, 5, 6)
|
4, 5, 6)
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
with debug.Session() as session:
|
with debug.Session() as session:
|
||||||
with run(session, target(code_to_debug)):
|
with run(session, target(code_to_debug)):
|
||||||
bp_markers = ["bp1-requested", "bp2-requested", "bp3-requested"]
|
count = 5 if sys.version_info < (3,) else 3
|
||||||
if sys.version_info < (3,):
|
requested_markers = ["r" + str(i) for i in range(0, count)]
|
||||||
bp_markers += ["bp4-requested-1", "bp4-requested-2"]
|
|
||||||
|
|
||||||
bps = session.set_breakpoints(code_to_debug, bp_markers)
|
bps = session.set_breakpoints(code_to_debug, requested_markers)
|
||||||
actual_lines = [bp["line"] for bp in bps]
|
actual_lines = [bp["line"] for bp in bps]
|
||||||
|
|
||||||
if sys.version_info >= (3, 9):
|
expected_markers = []
|
||||||
expected_markers = ["bp1-expected", "bp2-requested", "bp2-requested"]
|
for r in requested_markers:
|
||||||
elif sys.version_info >= (3, 8):
|
e_generic = "e" + r[1:]
|
||||||
# See: https://bugs.python.org/issue38508
|
e_versioned = e_generic + "-" + str(sys.version_info.major) + str(sys.version_info.minor)
|
||||||
expected_markers = ["bp1-expected", "bp2-requested", "bp3-expected"]
|
for e in e_versioned, e_generic, r:
|
||||||
else:
|
if e in code_to_debug.lines:
|
||||||
expected_markers = ["bp1-expected", "bp2-expected", "bp3-expected"]
|
expected_markers.append(e)
|
||||||
if sys.version_info < (3,):
|
break
|
||||||
expected_markers += ["bp4-expected", "bp4-expected"]
|
|
||||||
expected_lines = [
|
expected_lines = [
|
||||||
code_to_debug.lines[marker] for marker in expected_markers
|
code_to_debug.lines[marker] for marker in expected_markers
|
||||||
]
|
]
|
||||||
|
|
||||||
assert actual_lines == expected_lines
|
assert actual_lines == expected_lines
|
||||||
|
|
||||||
# Now let's make sure that we hit all of the expected breakpoints,
|
# Now let's make sure that we hit all of the expected breakpoints,
|
||||||
|
|
@ -377,10 +377,9 @@ def test_invalid_breakpoints(pyfile, target, run):
|
||||||
# so remove duplicates first.
|
# so remove duplicates first.
|
||||||
expected_lines = sorted(set(expected_lines))
|
expected_lines = sorted(set(expected_lines))
|
||||||
if (3, 8) <= sys.version_info < (3, 9):
|
if (3, 8) <= sys.version_info < (3, 9):
|
||||||
# We'll actually hit @bp3-expected and later @bp2-requested
|
# We'll actually hit @e2-38 first, and only then @r1, because there's
|
||||||
# (there's a line event when the list creation is finished
|
# a line event for [ when the list creation is finished on 3.8).
|
||||||
# at the start of the list creation on 3.8).
|
# See https://bugs.python.org/issue38508 for details.
|
||||||
# See: https://bugs.python.org/issue38508
|
|
||||||
expected_lines[1], expected_lines[2] = expected_lines[2], expected_lines[1]
|
expected_lines[1], expected_lines[2] = expected_lines[2], expected_lines[1]
|
||||||
|
|
||||||
while expected_lines:
|
while expected_lines:
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,17 @@
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
import sys
|
||||||
|
|
||||||
from debugpy.common import compat
|
from debugpy.common import compat
|
||||||
from tests import code, debug, log, net, test_data
|
from tests import code, debug, log, net, test_data
|
||||||
from tests.debug import runners, targets
|
from tests.debug import runners, targets
|
||||||
from tests.patterns import some
|
from tests.patterns import some
|
||||||
|
|
||||||
pytestmark = pytest.mark.timeout(60)
|
pytestmark = [
|
||||||
|
pytest.mark.timeout(60),
|
||||||
|
pytest.mark.skipif(sys.version_info >= (3, 10), reason="https://github.com/microsoft/debugpy/issues/689"),
|
||||||
|
]
|
||||||
|
|
||||||
django_server = net.WebServer(net.get_test_server_port(8000, 8100))
|
django_server = net.WebServer(net.get_test_server_port(8000, 8100))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,14 @@
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import sys
|
||||||
|
|
||||||
from tests import debug
|
from tests import debug
|
||||||
from tests.patterns import some
|
from tests.patterns import some
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.version_info >= (3, 10), reason="https://github.com/microsoft/debugpy/issues/688")
|
||||||
def test_gevent(pyfile, target, run):
|
def test_gevent(pyfile, target, run):
|
||||||
@pyfile
|
@pyfile
|
||||||
def code_to_debug():
|
def code_to_debug():
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
|
setuptools>=57.4.0
|
||||||
|
|
||||||
## Used to run the tests:
|
## Used to run the tests:
|
||||||
|
|
||||||
# pytest>=5 does not support Python 2.7
|
pytest
|
||||||
pytest<5
|
pytest-xdist
|
||||||
|
|
||||||
# pytest-xdist>=2 does not support Python 2.7
|
|
||||||
pytest-xdist<2
|
|
||||||
|
|
||||||
pytest-cov
|
pytest-cov
|
||||||
pytest-timeout
|
pytest-timeout
|
||||||
tox
|
tox
|
||||||
|
|
@ -19,5 +17,4 @@ psutil
|
||||||
django
|
django
|
||||||
requests
|
requests
|
||||||
gevent
|
gevent
|
||||||
|
|
||||||
flask>=1.1.2
|
flask>=1.1.2
|
||||||
|
|
|
||||||
22
tests/requirements27.txt
Normal file
22
tests/requirements27.txt
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
## Used to run the tests:
|
||||||
|
|
||||||
|
# pytest>=5 does not support Python 2.7
|
||||||
|
pytest<5
|
||||||
|
|
||||||
|
# pytest-xdist>=2 does not support Python 2.7
|
||||||
|
pytest-xdist<2
|
||||||
|
|
||||||
|
pytest-cov
|
||||||
|
pytest-timeout
|
||||||
|
tox
|
||||||
|
|
||||||
|
## Used by test helpers:
|
||||||
|
|
||||||
|
psutil
|
||||||
|
|
||||||
|
## Used in Python code that is run/debugged by the tests:
|
||||||
|
|
||||||
|
django
|
||||||
|
requests
|
||||||
|
gevent
|
||||||
|
flask>=1.1.2
|
||||||
20
tests/requirements35.txt
Normal file
20
tests/requirements35.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
setuptools
|
||||||
|
|
||||||
|
## Used to run the tests:
|
||||||
|
|
||||||
|
pytest
|
||||||
|
pytest-xdist
|
||||||
|
pytest-cov
|
||||||
|
pytest-timeout
|
||||||
|
tox
|
||||||
|
|
||||||
|
## Used by test helpers:
|
||||||
|
|
||||||
|
psutil
|
||||||
|
|
||||||
|
## Used in Python code that is run/debugged by the tests:
|
||||||
|
|
||||||
|
django
|
||||||
|
requests
|
||||||
|
gevent
|
||||||
|
flask>=1.1.2
|
||||||
8
tox.ini
8
tox.ini
|
|
@ -1,5 +1,5 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py{27,35,36,37,38}{,-cov}
|
envlist = py{27,35,36,37,38,39,310}{,-cov}
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = -rtests/requirements.txt
|
deps = -rtests/requirements.txt
|
||||||
|
|
@ -9,3 +9,9 @@ setenv =
|
||||||
commands =
|
commands =
|
||||||
!cov: pytest {posargs}
|
!cov: pytest {posargs}
|
||||||
cov: pytest --cov --cov-append --cov-config=.coveragerc {posargs}
|
cov: pytest --cov --cov-append --cov-config=.coveragerc {posargs}
|
||||||
|
|
||||||
|
[testenv:py27]
|
||||||
|
deps = -rtests/requirements27.txt
|
||||||
|
|
||||||
|
[testenv:py35]
|
||||||
|
deps = -rtests/requirements35.txt
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue