mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Updates from PyDev.Debugger
This commit is contained in:
@@ -1,16 +1,62 @@
|
||||
# License: EPL
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import pydev_log
|
||||
try:
|
||||
xrange
|
||||
except:
|
||||
xrange = range
|
||||
|
||||
#===============================================================================
|
||||
# Things that are dependent on having the pydevd debugger
|
||||
#===============================================================================
|
||||
def log_debug(msg):
|
||||
import pydev_log
|
||||
pydev_log.debug(msg)
|
||||
|
||||
def log_error_once(msg):
|
||||
import pydev_log
|
||||
pydev_log.error_once(msg)
|
||||
|
||||
pydev_src_dir = os.path.dirname(__file__)
|
||||
|
||||
from pydevd_constants import xrange
|
||||
def _get_python_c_args(host, port, indC, args):
|
||||
return ("import sys; sys.path.append(r'%s'); import pydevd; "
|
||||
"pydevd.settrace(host='%s', port=%s, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True); %s"
|
||||
) % (
|
||||
pydev_src_dir,
|
||||
host,
|
||||
port,
|
||||
args[indC + 1])
|
||||
|
||||
def _get_host_port():
|
||||
import pydevd
|
||||
host, port = pydevd.dispatch()
|
||||
return host, port
|
||||
|
||||
def _is_managed_arg(arg):
|
||||
if arg.endswith('pydevd.py'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _on_forked_process():
|
||||
import pydevd
|
||||
pydevd.threadingCurrentThread().__pydevd_main_thread = True
|
||||
pydevd.settrace_forked()
|
||||
|
||||
def _on_set_trace_for_new_thread():
|
||||
from pydevd_comm import GetGlobalDebugger
|
||||
global_debugger = GetGlobalDebugger()
|
||||
if global_debugger is not None:
|
||||
global_debugger.SetTrace(global_debugger.trace_dispatch)
|
||||
|
||||
#===============================================================================
|
||||
# Things related to monkey-patching
|
||||
#===============================================================================
|
||||
def is_python(path):
|
||||
if path.endswith("'") or path.endswith('"'):
|
||||
path = path[1:len(path)-1]
|
||||
path = path[1:len(path) - 1]
|
||||
filename = os.path.basename(path).lower()
|
||||
for name in ['python', 'jython', 'pypy']:
|
||||
if filename.find(name) != -1:
|
||||
@@ -20,7 +66,7 @@ def is_python(path):
|
||||
|
||||
def patch_args(args):
|
||||
try:
|
||||
pydev_log.debug("Patching args: %s"% str(args))
|
||||
log_debug("Patching args: %s"% str(args))
|
||||
|
||||
import sys
|
||||
new_args = []
|
||||
@@ -35,19 +81,16 @@ def patch_args(args):
|
||||
indC = -1
|
||||
|
||||
if indC != -1:
|
||||
import pydevd
|
||||
host, port = pydevd.dispatch()
|
||||
host, port = _get_host_port()
|
||||
|
||||
if port is not None:
|
||||
new_args.extend(args)
|
||||
new_args[indC + 1] = ("import sys; sys.path.append(r'%s'); import pydevd; "
|
||||
"pydevd.settrace(host='%s', port=%s, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True); %s") % (
|
||||
pydev_src_dir, host, port, args[indC + 1])
|
||||
new_args[indC + 1] = _get_python_c_args(host, port, indC, args)
|
||||
return new_args
|
||||
else:
|
||||
new_args.append(args[0])
|
||||
else:
|
||||
pydev_log.debug("Process is not python, returning.")
|
||||
log_debug("Process is not python, returning.")
|
||||
return args
|
||||
|
||||
i = 1
|
||||
@@ -58,7 +101,7 @@ def patch_args(args):
|
||||
break
|
||||
i += 1
|
||||
|
||||
if i < len(args) and args[i].endswith('pydevd.py'): #no need to add pydevd twice
|
||||
if i < len(args) and _is_managed_arg(args[i]): # no need to add pydevd twice
|
||||
return args
|
||||
|
||||
for x in sys.original_argv:
|
||||
@@ -108,7 +151,7 @@ def str_to_args_windows(args):
|
||||
for i in xrange(args_len):
|
||||
ch = args[i]
|
||||
if (ch == '\\'):
|
||||
backslashes+=1
|
||||
backslashes += 1
|
||||
continue
|
||||
elif (backslashes != 0):
|
||||
if ch == '"':
|
||||
@@ -122,16 +165,16 @@ def str_to_args_windows(args):
|
||||
buf += '"'
|
||||
backslashes = 0
|
||||
continue
|
||||
# else fall through to switch
|
||||
# else fall through to switch
|
||||
else:
|
||||
# false alarm, treat passed backslashes literally...
|
||||
if (state == DEFAULT):
|
||||
state = ARG
|
||||
|
||||
while backslashes > 0:
|
||||
backslashes-=1
|
||||
backslashes -= 1
|
||||
buf += '\\'
|
||||
# fall through to switch
|
||||
# fall through to switch
|
||||
if ch in (' ', '\t'):
|
||||
if (state == DEFAULT):
|
||||
# skip
|
||||
@@ -156,9 +199,10 @@ def str_to_args_windows(args):
|
||||
# Two consecutive double quotes inside a double-quoted argument are interpreted as
|
||||
# a single double quote.
|
||||
buf += '"'
|
||||
i+=1
|
||||
i += 1
|
||||
elif len(buf) == 0:
|
||||
# empty string on Windows platform. Account for bug in constructor of JDK's java.lang.ProcessImpl.
|
||||
# empty string on Windows platform. Account for bug in constructor of
|
||||
# JDK's java.lang.ProcessImpl.
|
||||
result.append("\"\"")
|
||||
state = DEFAULT
|
||||
else:
|
||||
@@ -180,7 +224,7 @@ def patch_arg_str_win(arg_str):
|
||||
if not is_python(args[0]):
|
||||
return arg_str
|
||||
arg_str = args_to_str(patch_args(args))
|
||||
pydev_log.debug("New args: %s" % arg_str)
|
||||
log_debug("New args: %s" % arg_str)
|
||||
return arg_str
|
||||
|
||||
def monkey_patch_module(module, funcname, create_func):
|
||||
@@ -196,11 +240,9 @@ def monkey_patch_os(funcname, create_func):
|
||||
|
||||
|
||||
def warn_multiproc():
|
||||
import pydev_log
|
||||
|
||||
pydev_log.error_once(
|
||||
"pydev debugger: New process is launching (breakpoints won't work in the new process).\n"
|
||||
"pydev debugger: To debug that process please enable 'Attach to subprocess automatically while debugging?' option in the debugger settings.\n")
|
||||
log_error_once(
|
||||
"pydev debugger: New process is launching (breakpoints won't work in the new process).\n"
|
||||
"pydev debugger: To debug that process please enable 'Attach to subprocess automatically while debugging?' option in the debugger settings.\n")
|
||||
|
||||
|
||||
def create_warn_multiproc(original_name):
|
||||
@@ -226,6 +268,7 @@ os.execlpe(file, arg0, arg1, ..., env)
|
||||
return getattr(os, original_name)(path, *args)
|
||||
return new_execl
|
||||
|
||||
|
||||
def create_execv(original_name):
|
||||
def new_execv(path, args):
|
||||
'''
|
||||
@@ -236,6 +279,7 @@ os.execvp(file, args)
|
||||
return getattr(os, original_name)(path, patch_args(args))
|
||||
return new_execv
|
||||
|
||||
|
||||
def create_execve(original_name):
|
||||
"""
|
||||
os.execve(path, args, env)
|
||||
@@ -258,6 +302,7 @@ os.spawnlp(mode, file, arg0, arg1, ...)
|
||||
return getattr(os, original_name)(mode, path, *args)
|
||||
return new_spawnl
|
||||
|
||||
|
||||
def create_spawnv(original_name):
|
||||
def new_spawnv(mode, path, args):
|
||||
'''
|
||||
@@ -268,6 +313,7 @@ os.spawnvp(mode, file, args)
|
||||
return getattr(os, original_name)(mode, path, patch_args(args))
|
||||
return new_spawnv
|
||||
|
||||
|
||||
def create_spawnve(original_name):
|
||||
"""
|
||||
os.spawnve(mode, path, args, env)
|
||||
@@ -278,6 +324,7 @@ os.spawnvpe(mode, file, args, env)
|
||||
return getattr(os, original_name)(mode, path, patch_args(args), env)
|
||||
return new_spawnve
|
||||
|
||||
|
||||
def create_fork_exec(original_name):
|
||||
"""
|
||||
_posixsubprocess.fork_exec(args, executable_list, close_fds, ... (13 more))
|
||||
@@ -288,6 +335,7 @@ _posixsubprocess.fork_exec(args, executable_list, close_fds, ... (13 more))
|
||||
return getattr(_posixsubprocess, original_name)(args, *other_args)
|
||||
return new_fork_exec
|
||||
|
||||
|
||||
def create_CreateProcess(original_name):
|
||||
"""
|
||||
CreateProcess(*args, **kwargs)
|
||||
@@ -300,6 +348,7 @@ CreateProcess(*args, **kwargs)
|
||||
return getattr(_subprocess, original_name)(appName, patch_arg_str_win(commandLine), *args)
|
||||
return new_CreateProcess
|
||||
|
||||
|
||||
def create_CreateProcessWarnMultiproc(original_name):
|
||||
"""
|
||||
CreateProcess(*args, **kwargs)
|
||||
@@ -313,27 +362,26 @@ CreateProcess(*args, **kwargs)
|
||||
return getattr(_subprocess, original_name)(*args)
|
||||
return new_CreateProcess
|
||||
|
||||
|
||||
def create_fork(original_name):
|
||||
def new_fork():
|
||||
import os
|
||||
child_process = getattr(os, original_name)() # fork
|
||||
child_process = getattr(os, original_name)() # fork
|
||||
if not child_process:
|
||||
import pydevd
|
||||
pydevd.threadingCurrentThread().__pydevd_main_thread = True
|
||||
|
||||
pydevd.settrace_forked()
|
||||
_on_forked_process()
|
||||
return child_process
|
||||
return new_fork
|
||||
|
||||
|
||||
def patch_new_process_functions():
|
||||
#os.execl(path, arg0, arg1, ...)
|
||||
#os.execle(path, arg0, arg1, ..., env)
|
||||
#os.execlp(file, arg0, arg1, ...)
|
||||
#os.execlpe(file, arg0, arg1, ..., env)
|
||||
#os.execv(path, args)
|
||||
#os.execve(path, args, env)
|
||||
#os.execvp(file, args)
|
||||
#os.execvpe(file, args, env)
|
||||
# os.execl(path, arg0, arg1, ...)
|
||||
# os.execle(path, arg0, arg1, ..., env)
|
||||
# os.execlp(file, arg0, arg1, ...)
|
||||
# os.execlpe(file, arg0, arg1, ..., env)
|
||||
# os.execv(path, args)
|
||||
# os.execve(path, args, env)
|
||||
# os.execvp(file, args)
|
||||
# os.execvpe(file, args, env)
|
||||
monkey_patch_os('execl', create_execl)
|
||||
monkey_patch_os('execle', create_execl)
|
||||
monkey_patch_os('execlp', create_execl)
|
||||
@@ -343,14 +391,14 @@ def patch_new_process_functions():
|
||||
monkey_patch_os('execvp', create_execv)
|
||||
monkey_patch_os('execvpe', create_execve)
|
||||
|
||||
#os.spawnl(mode, path, ...)
|
||||
#os.spawnle(mode, path, ..., env)
|
||||
#os.spawnlp(mode, file, ...)
|
||||
#os.spawnlpe(mode, file, ..., env)
|
||||
#os.spawnv(mode, path, args)
|
||||
#os.spawnve(mode, path, args, env)
|
||||
#os.spawnvp(mode, file, args)
|
||||
#os.spawnvpe(mode, file, args, env)
|
||||
# os.spawnl(mode, path, ...)
|
||||
# os.spawnle(mode, path, ..., env)
|
||||
# os.spawnlp(mode, file, ...)
|
||||
# os.spawnlpe(mode, file, ..., env)
|
||||
# os.spawnv(mode, path, args)
|
||||
# os.spawnve(mode, path, args, env)
|
||||
# os.spawnvp(mode, file, args)
|
||||
# os.spawnvpe(mode, file, args, env)
|
||||
|
||||
monkey_patch_os('spawnl', create_spawnl)
|
||||
monkey_patch_os('spawnle', create_spawnl)
|
||||
@@ -369,7 +417,7 @@ def patch_new_process_functions():
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
#Windows
|
||||
# Windows
|
||||
try:
|
||||
import _subprocess
|
||||
except ImportError:
|
||||
@@ -403,7 +451,7 @@ def patch_new_process_functions_with_warning():
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
#Windows
|
||||
# Windows
|
||||
try:
|
||||
import _subprocess
|
||||
except ImportError:
|
||||
@@ -411,7 +459,6 @@ def patch_new_process_functions_with_warning():
|
||||
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcessWarnMultiproc)
|
||||
|
||||
|
||||
|
||||
class _NewThreadStartupWithTrace:
|
||||
|
||||
def __init__(self, original_func, args, kwargs):
|
||||
@@ -420,10 +467,9 @@ class _NewThreadStartupWithTrace:
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __call__(self):
|
||||
_on_set_trace_for_new_thread()
|
||||
from pydevd_comm import GetGlobalDebugger
|
||||
global_debugger = GetGlobalDebugger()
|
||||
if global_debugger is not None:
|
||||
global_debugger.SetTrace(global_debugger.trace_dispatch)
|
||||
|
||||
if global_debugger.thread_analyser is not None:
|
||||
# we can detect start_new_thread only here
|
||||
@@ -435,6 +481,7 @@ class _NewThreadStartupWithTrace:
|
||||
|
||||
return self.original_func(*self.args, **self.kwargs)
|
||||
|
||||
|
||||
class _NewThreadStartupWithoutTrace:
|
||||
|
||||
def __init__(self, original_func, args, kwargs):
|
||||
@@ -447,6 +494,7 @@ class _NewThreadStartupWithoutTrace:
|
||||
|
||||
_UseNewThreadStartup = _NewThreadStartupWithTrace
|
||||
|
||||
|
||||
def _get_threading_modules_to_patch():
|
||||
threading_modules_to_patch = []
|
||||
try:
|
||||
@@ -460,7 +508,6 @@ def _get_threading_modules_to_patch():
|
||||
threading_modules_to_patch = _get_threading_modules_to_patch()
|
||||
|
||||
|
||||
|
||||
def patch_thread_module(thread):
|
||||
|
||||
if getattr(thread, '_original_start_new_thread', None) is None:
|
||||
@@ -468,7 +515,6 @@ def patch_thread_module(thread):
|
||||
else:
|
||||
_original_start_new_thread = thread._original_start_new_thread
|
||||
|
||||
|
||||
class ClassWithPydevStartNewThread:
|
||||
|
||||
def pydev_start_new_thread(self, function, args=(), kwargs={}):
|
||||
@@ -496,10 +542,12 @@ def patch_thread_module(thread):
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def patch_thread_modules():
|
||||
for t in threading_modules_to_patch:
|
||||
patch_thread_module(t)
|
||||
|
||||
|
||||
def undo_patch_thread_modules():
|
||||
for t in threading_modules_to_patch:
|
||||
try:
|
||||
@@ -512,6 +560,7 @@ def undo_patch_thread_modules():
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def disable_trace_thread_modules():
|
||||
'''
|
||||
Can be used to temporarily stop tracing threads created with thread.start_new_thread.
|
||||
@@ -527,6 +576,7 @@ def enable_trace_thread_modules():
|
||||
global _UseNewThreadStartup
|
||||
_UseNewThreadStartup = _NewThreadStartupWithTrace
|
||||
|
||||
|
||||
def get_original_start_new_thread(threading_module):
|
||||
try:
|
||||
return threading_module._original_start_new_thread
|
||||
|
||||
Reference in New Issue
Block a user