mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Pydev.Debugger updated.
This commit is contained in:
@@ -1,2 +1,9 @@
|
||||
PyDev.Debugger
|
||||
==============
|
||||
|
||||
[](https://travis-ci.org/fabioz/PyDev.Debugger)
|
||||
|
||||
This repository contains the sources for the Debugger used in PyDev & PyCharm.
|
||||
|
||||
It should be compatible with Python 2.4 onwards (as well as Jython 2.2.1, IronPython and PyPy -- and any
|
||||
other variant which properly supports the Python structure for debuggers -- i.e.: sys.settrace/threading.settrace).
|
||||
@@ -4,6 +4,10 @@ import sys
|
||||
|
||||
from _pydev_tipper_common import DoFind
|
||||
|
||||
try:
|
||||
xrange
|
||||
except:
|
||||
xrange = range
|
||||
|
||||
#completion types.
|
||||
TYPE_IMPORT = '0'
|
||||
@@ -19,20 +23,20 @@ def _imp(name, log=None):
|
||||
except:
|
||||
if '.' in name:
|
||||
sub = name[0:name.rfind('.')]
|
||||
|
||||
|
||||
if log is not None:
|
||||
log.AddContent('Unable to import', name, 'trying with', sub)
|
||||
log.AddException()
|
||||
|
||||
|
||||
return _imp(sub, log)
|
||||
else:
|
||||
s = 'Unable to import module: %s - sys.path: %s' % (str(name), sys.path)
|
||||
if log is not None:
|
||||
log.AddContent(s)
|
||||
log.AddException()
|
||||
|
||||
|
||||
raise ImportError(s)
|
||||
|
||||
|
||||
|
||||
IS_IPY = False
|
||||
if sys.platform == 'cli':
|
||||
@@ -53,9 +57,9 @@ if sys.platform == 'cli':
|
||||
clr.AddReference(name)
|
||||
except:
|
||||
pass #That's OK (not dot net module).
|
||||
|
||||
|
||||
return _old_imp(initial_name, log)
|
||||
|
||||
|
||||
|
||||
|
||||
def GetFile(mod):
|
||||
@@ -69,19 +73,19 @@ def GetFile(mod):
|
||||
filename = f[:-4] + '.py'
|
||||
if os.path.exists(filename):
|
||||
f = filename
|
||||
|
||||
|
||||
return f
|
||||
|
||||
def Find(name, log=None):
|
||||
f = None
|
||||
|
||||
|
||||
mod = _imp(name, log)
|
||||
parent = mod
|
||||
foundAs = ''
|
||||
|
||||
|
||||
if inspect.ismodule(mod):
|
||||
f = GetFile(mod)
|
||||
|
||||
|
||||
components = name.split('.')
|
||||
|
||||
old_comp = None
|
||||
@@ -94,22 +98,22 @@ def Find(name, log=None):
|
||||
except AttributeError:
|
||||
if old_comp != comp:
|
||||
raise
|
||||
|
||||
|
||||
if inspect.ismodule(mod):
|
||||
f = GetFile(mod)
|
||||
else:
|
||||
if len(foundAs) > 0:
|
||||
foundAs = foundAs + '.'
|
||||
foundAs = foundAs + comp
|
||||
|
||||
|
||||
old_comp = comp
|
||||
|
||||
|
||||
return f, mod, parent, foundAs
|
||||
|
||||
def Search(data):
|
||||
'''@return file, line, col
|
||||
'''
|
||||
|
||||
|
||||
data = data.replace('\n', '')
|
||||
if data.endswith('.'):
|
||||
data = data.rstrip('.')
|
||||
@@ -118,19 +122,19 @@ def Search(data):
|
||||
return DoFind(f, mod), foundAs
|
||||
except:
|
||||
return DoFind(f, parent), foundAs
|
||||
|
||||
|
||||
|
||||
|
||||
def GenerateTip(data, log=None):
|
||||
data = data.replace('\n', '')
|
||||
if data.endswith('.'):
|
||||
data = data.rstrip('.')
|
||||
|
||||
|
||||
f, mod, parent, foundAs = Find(data, log)
|
||||
#print_ >> open('temp.txt', 'w'), f
|
||||
tips = GenerateImportsTipForModule(mod)
|
||||
return f, tips
|
||||
|
||||
|
||||
|
||||
|
||||
def CheckChar(c):
|
||||
if c == '-' or c == '.':
|
||||
return '_'
|
||||
@@ -146,7 +150,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
name, doc, args, type (from the TYPE_* constants)
|
||||
'''
|
||||
ret = []
|
||||
|
||||
|
||||
if dirComps is None:
|
||||
dirComps = dir(obj_to_complete)
|
||||
if hasattr(obj_to_complete, '__dict__'):
|
||||
@@ -155,22 +159,22 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
dirComps.append('__class__')
|
||||
|
||||
getCompleteInfo = True
|
||||
|
||||
|
||||
if len(dirComps) > 1000:
|
||||
#ok, we don't want to let our users wait forever...
|
||||
#ok, we don't want to let our users wait forever...
|
||||
#no complete info for you...
|
||||
|
||||
|
||||
getCompleteInfo = False
|
||||
|
||||
|
||||
dontGetDocsOn = (float, int, str, tuple, list)
|
||||
for d in dirComps:
|
||||
|
||||
|
||||
if d is None:
|
||||
continue
|
||||
|
||||
|
||||
if not filter(d):
|
||||
continue
|
||||
|
||||
|
||||
args = ''
|
||||
|
||||
try:
|
||||
@@ -182,18 +186,18 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
if getCompleteInfo:
|
||||
try:
|
||||
retType = TYPE_BUILTIN
|
||||
|
||||
|
||||
#check if we have to get docs
|
||||
getDoc = True
|
||||
for class_ in dontGetDocsOn:
|
||||
|
||||
|
||||
if isinstance(obj, class_):
|
||||
getDoc = False
|
||||
break
|
||||
|
||||
|
||||
doc = ''
|
||||
if getDoc:
|
||||
#no need to get this info... too many constants are defined and
|
||||
#no need to get this info... too many constants are defined and
|
||||
#makes things much slower (passing all that through sockets takes quite some time)
|
||||
try:
|
||||
doc = inspect.getdoc(obj)
|
||||
@@ -201,12 +205,12 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
doc = ''
|
||||
except: #may happen on jython when checking java classes (so, just ignore it)
|
||||
doc = ''
|
||||
|
||||
|
||||
|
||||
|
||||
if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
|
||||
try:
|
||||
args, vargs, kwargs, defaults = inspect.getargspec(obj)
|
||||
|
||||
|
||||
r = ''
|
||||
for a in (args):
|
||||
if len(r) > 0:
|
||||
@@ -250,7 +254,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
if major:
|
||||
args = major[major.index('('):]
|
||||
found = True
|
||||
|
||||
|
||||
|
||||
if not found:
|
||||
i = doc.find('->')
|
||||
@@ -260,12 +264,12 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
i = doc.find('\n')
|
||||
if i < 0:
|
||||
i = doc.find('\r')
|
||||
|
||||
|
||||
|
||||
|
||||
if i > 0:
|
||||
s = doc[0:i]
|
||||
s = s.strip()
|
||||
|
||||
|
||||
#let's see if we have a docstring in the first line
|
||||
if s[-1] == ')':
|
||||
start = s.find('(')
|
||||
@@ -275,21 +279,21 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
end = s.find(')')
|
||||
if end <= 0:
|
||||
end = len(s)
|
||||
|
||||
|
||||
args = s[start:end]
|
||||
if not args[-1] == ')':
|
||||
args = args + ')'
|
||||
|
||||
|
||||
|
||||
|
||||
#now, get rid of unwanted chars
|
||||
l = len(args) - 1
|
||||
r = []
|
||||
for i in range(len(args)):
|
||||
for i in xrange(len(args)):
|
||||
if i == 0 or i == l:
|
||||
r.append(args[i])
|
||||
else:
|
||||
r.append(CheckChar(args[i]))
|
||||
|
||||
|
||||
args = ''.join(r)
|
||||
|
||||
if IS_IPY:
|
||||
@@ -305,43 +309,43 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
retType = TYPE_FUNCTION
|
||||
|
||||
|
||||
elif inspect.isclass(obj):
|
||||
retType = TYPE_CLASS
|
||||
|
||||
|
||||
elif inspect.ismodule(obj):
|
||||
retType = TYPE_IMPORT
|
||||
|
||||
|
||||
else:
|
||||
retType = TYPE_ATTR
|
||||
|
||||
|
||||
|
||||
|
||||
#add token and doc to return - assure only strings.
|
||||
ret.append((d, doc, args, retType))
|
||||
|
||||
|
||||
except: #just ignore and get it without aditional info
|
||||
ret.append((d, '', args, TYPE_BUILTIN))
|
||||
|
||||
|
||||
else: #getCompleteInfo == False
|
||||
if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
|
||||
retType = TYPE_FUNCTION
|
||||
|
||||
|
||||
elif inspect.isclass(obj):
|
||||
retType = TYPE_CLASS
|
||||
|
||||
|
||||
elif inspect.ismodule(obj):
|
||||
retType = TYPE_IMPORT
|
||||
|
||||
|
||||
else:
|
||||
retType = TYPE_ATTR
|
||||
#ok, no complete info, let's try to do this as fast and clean as possible
|
||||
#so, no docs for this kind of information, only the signatures
|
||||
ret.append((d, '', str(args), retType))
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -27,13 +27,7 @@ Here are some of the useful functions provided by this module:
|
||||
__author__ = 'Ka-Ping Yee <ping@lfw.org>'
|
||||
__date__ = '1 Jan 2001'
|
||||
|
||||
import sys
|
||||
import os
|
||||
import types
|
||||
import string
|
||||
import re
|
||||
import imp
|
||||
import tokenize
|
||||
import sys, os, types, string, re, imp, tokenize
|
||||
|
||||
# ----------------------------------------------------------- type-checking
|
||||
def ismodule(object):
|
||||
|
||||
@@ -14,13 +14,18 @@ except NameError: # version < 2.3 -- didn't have the True/False builtins
|
||||
import __builtin__
|
||||
setattr(__builtin__, 'True', 1)
|
||||
setattr(__builtin__, 'False', 0)
|
||||
|
||||
|
||||
|
||||
|
||||
from org.python.core import PyReflectedFunction #@UnresolvedImport
|
||||
|
||||
from org.python import core #@UnresolvedImport
|
||||
from org.python.core import PyClass #@UnresolvedImport
|
||||
|
||||
try:
|
||||
xrange
|
||||
except:
|
||||
xrange = range
|
||||
|
||||
|
||||
#completion types.
|
||||
TYPE_IMPORT = '0'
|
||||
@@ -48,11 +53,11 @@ def Find(name):
|
||||
name = 'org.python.core.PyString'
|
||||
elif name == '__builtin__.dict':
|
||||
name = 'org.python.core.PyDictionary'
|
||||
|
||||
|
||||
mod = _imp(name)
|
||||
parent = mod
|
||||
foundAs = ''
|
||||
|
||||
|
||||
if hasattr(mod, '__file__'):
|
||||
f = mod.__file__
|
||||
|
||||
@@ -68,29 +73,29 @@ def Find(name):
|
||||
except AttributeError:
|
||||
if old_comp != comp:
|
||||
raise
|
||||
|
||||
|
||||
if hasattr(mod, '__file__'):
|
||||
f = mod.__file__
|
||||
else:
|
||||
if len(foundAs) > 0:
|
||||
foundAs = foundAs + '.'
|
||||
foundAs = foundAs + comp
|
||||
|
||||
|
||||
old_comp = comp
|
||||
|
||||
|
||||
return f, mod, parent, foundAs
|
||||
|
||||
def formatParamClassName(paramClassName):
|
||||
if paramClassName.startswith('['):
|
||||
if paramClassName == '[C':
|
||||
paramClassName = 'char[]'
|
||||
|
||||
|
||||
elif paramClassName == '[B':
|
||||
paramClassName = 'byte[]'
|
||||
|
||||
|
||||
elif paramClassName == '[I':
|
||||
paramClassName = 'int[]'
|
||||
|
||||
|
||||
elif paramClassName.startswith('[L') and paramClassName.endswith(';'):
|
||||
paramClassName = paramClassName[2:-1]
|
||||
paramClassName += '[]'
|
||||
@@ -101,17 +106,17 @@ def GenerateTip(data, log=None):
|
||||
data = data.replace('\n', '')
|
||||
if data.endswith('.'):
|
||||
data = data.rstrip('.')
|
||||
|
||||
|
||||
f, mod, parent, foundAs = Find(data)
|
||||
tips = GenerateImportsTipForModule(mod)
|
||||
return f, tips
|
||||
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# Info
|
||||
#=======================================================================================================================
|
||||
class Info:
|
||||
|
||||
|
||||
def __init__(self, name, **kwargs):
|
||||
self.name = name
|
||||
self.doc = kwargs.get('doc', None)
|
||||
@@ -119,47 +124,47 @@ class Info:
|
||||
self.varargs = kwargs.get('varargs', None) #string
|
||||
self.kwargs = kwargs.get('kwargs', None) #string
|
||||
self.ret = kwargs.get('ret', None) #string
|
||||
|
||||
|
||||
def basicAsStr(self):
|
||||
'''@returns this class information as a string (just basic format)
|
||||
'''
|
||||
|
||||
|
||||
s = 'function:%s args=%s, varargs=%s, kwargs=%s, docs:%s' % \
|
||||
(str(self.name), str(self.args), str(self.varargs), str(self.kwargs), str(self.doc))
|
||||
return s
|
||||
|
||||
|
||||
|
||||
def getAsDoc(self):
|
||||
s = str(self.name)
|
||||
if self.doc:
|
||||
s += '\n@doc %s\n' % str(self.doc)
|
||||
|
||||
|
||||
if self.args:
|
||||
s += '\n@params '
|
||||
for arg in self.args:
|
||||
s += str(formatParamClassName(arg))
|
||||
s += ' '
|
||||
|
||||
|
||||
if self.varargs:
|
||||
s += '\n@varargs '
|
||||
s += str(self.varargs)
|
||||
|
||||
|
||||
if self.kwargs:
|
||||
s += '\n@kwargs '
|
||||
s += str(self.kwargs)
|
||||
|
||||
|
||||
if self.ret:
|
||||
s += '\n@return '
|
||||
s += str(formatParamClassName(str(self.ret)))
|
||||
|
||||
|
||||
return str(s)
|
||||
|
||||
|
||||
def isclass(cls):
|
||||
return isinstance(cls, core.PyClass)
|
||||
|
||||
def ismethod(func):
|
||||
'''this function should return the information gathered on a function
|
||||
|
||||
|
||||
@param func: this is the function we want to get info on
|
||||
@return a tuple where:
|
||||
0 = indicates whether the parameter passed is a method or not
|
||||
@@ -167,24 +172,24 @@ def ismethod(func):
|
||||
this is a list because when we have methods from java with the same name and different signatures,
|
||||
we actually have many methods, each with its own set of arguments
|
||||
'''
|
||||
|
||||
|
||||
try:
|
||||
if isinstance(func, core.PyFunction):
|
||||
#ok, this is from python, created by jython
|
||||
#print_ ' PyFunction'
|
||||
|
||||
|
||||
def getargs(func_code):
|
||||
"""Get information about the arguments accepted by a code object.
|
||||
|
||||
|
||||
Three things are returned: (args, varargs, varkw), where 'args' is
|
||||
a list of argument names (possibly containing nested lists), and
|
||||
'varargs' and 'varkw' are the names of the * and ** arguments or None."""
|
||||
|
||||
|
||||
nargs = func_code.co_argcount
|
||||
names = func_code.co_varnames
|
||||
args = list(names[:nargs])
|
||||
step = 0
|
||||
|
||||
|
||||
varargs = None
|
||||
if func_code.co_flags & func_code.CO_VARARGS:
|
||||
varargs = func_code.co_varnames[nargs]
|
||||
@@ -193,35 +198,35 @@ def ismethod(func):
|
||||
if func_code.co_flags & func_code.CO_VARKEYWORDS:
|
||||
varkw = func_code.co_varnames[nargs]
|
||||
return args, varargs, varkw
|
||||
|
||||
|
||||
args = getargs(func.func_code)
|
||||
return 1, [Info(func.func_name, args=args[0], varargs=args[1], kwargs=args[2], doc=func.func_doc)]
|
||||
|
||||
|
||||
if isinstance(func, core.PyMethod):
|
||||
#this is something from java itself, and jython just wrapped it...
|
||||
|
||||
|
||||
#things to play in func:
|
||||
#['__call__', '__class__', '__cmp__', '__delattr__', '__dir__', '__doc__', '__findattr__', '__name__', '_doget', 'im_class',
|
||||
#'im_func', 'im_self', 'toString']
|
||||
#print_ ' PyMethod'
|
||||
#that's the PyReflectedFunction... keep going to get it
|
||||
func = func.im_func
|
||||
|
||||
|
||||
if isinstance(func, PyReflectedFunction):
|
||||
#this is something from java itself, and jython just wrapped it...
|
||||
|
||||
|
||||
#print_ ' PyReflectedFunction'
|
||||
|
||||
|
||||
infos = []
|
||||
for i in range(len(func.argslist)):
|
||||
for i in xrange(len(func.argslist)):
|
||||
#things to play in func.argslist[i]:
|
||||
|
||||
|
||||
#'PyArgsCall', 'PyArgsKeywordsCall', 'REPLACE', 'StandardCall', 'args', 'compare', 'compareTo', 'data', 'declaringClass'
|
||||
#'flags', 'isStatic', 'matches', 'precedence']
|
||||
|
||||
|
||||
#print_ ' ', func.argslist[i].data.__class__
|
||||
#func.argslist[i].data.__class__ == java.lang.reflect.Method
|
||||
|
||||
|
||||
if func.argslist[i]:
|
||||
met = func.argslist[i].data
|
||||
name = met.getName()
|
||||
@@ -230,9 +235,9 @@ def ismethod(func):
|
||||
except AttributeError:
|
||||
ret = ''
|
||||
parameterTypes = met.getParameterTypes()
|
||||
|
||||
|
||||
args = []
|
||||
for j in range(len(parameterTypes)):
|
||||
for j in xrange(len(parameterTypes)):
|
||||
paramTypesClass = parameterTypes[j]
|
||||
try:
|
||||
try:
|
||||
@@ -246,7 +251,7 @@ def ismethod(func):
|
||||
except:
|
||||
paramClassName = repr(paramTypesClass) #just in case something else happens... it will at least be visible
|
||||
#if the parameter equals [C, it means it it a char array, so, let's change it
|
||||
|
||||
|
||||
a = formatParamClassName(paramClassName)
|
||||
#a = a.replace('[]','Array')
|
||||
#a = a.replace('Object', 'obj')
|
||||
@@ -255,18 +260,18 @@ def ismethod(func):
|
||||
#a = a.replace('Char', 'c')
|
||||
#a = a.replace('Double', 'd')
|
||||
args.append(a) #so we don't leave invalid code
|
||||
|
||||
|
||||
|
||||
|
||||
info = Info(name, args=args, ret=ret)
|
||||
#print_ info.basicAsStr()
|
||||
infos.append(info)
|
||||
|
||||
|
||||
return 1, infos
|
||||
except Exception:
|
||||
s = StringIO.StringIO()
|
||||
traceback.print_exc(file=s)
|
||||
return 1, [Info(str('ERROR'), doc=s.getvalue())]
|
||||
|
||||
|
||||
return 0, None
|
||||
|
||||
def ismodule(mod):
|
||||
@@ -274,7 +279,7 @@ def ismodule(mod):
|
||||
if not hasattr(mod, 'getClass') and not hasattr(mod, '__class__') \
|
||||
and hasattr(mod, '__name__'):
|
||||
return 1
|
||||
|
||||
|
||||
return isinstance(mod, core.PyModule)
|
||||
|
||||
|
||||
@@ -293,11 +298,11 @@ def dirObj(obj):
|
||||
except TypeError:
|
||||
#may happen on jython when getting the java.lang.Class class
|
||||
c = obj.getSuperclass(obj)
|
||||
|
||||
|
||||
while c != None:
|
||||
classes.append(c)
|
||||
c = c.getSuperclass()
|
||||
|
||||
|
||||
#get info about interfaces
|
||||
interfs = []
|
||||
for obj in classes:
|
||||
@@ -306,57 +311,57 @@ def dirObj(obj):
|
||||
except TypeError:
|
||||
interfs.extend(obj.getInterfaces(obj))
|
||||
classes.extend(interfs)
|
||||
|
||||
|
||||
#now is the time when we actually get info on the declared methods and fields
|
||||
for obj in classes:
|
||||
try:
|
||||
declaredMethods = obj.getDeclaredMethods()
|
||||
except TypeError:
|
||||
declaredMethods = obj.getDeclaredMethods(obj)
|
||||
|
||||
|
||||
try:
|
||||
declaredFields = obj.getDeclaredFields()
|
||||
except TypeError:
|
||||
declaredFields = obj.getDeclaredFields(obj)
|
||||
|
||||
for i in range(len(declaredMethods)):
|
||||
|
||||
for i in xrange(len(declaredMethods)):
|
||||
name = declaredMethods[i].getName()
|
||||
ret.append(name)
|
||||
found.put(name, 1)
|
||||
|
||||
for i in range(len(declaredFields)):
|
||||
|
||||
for i in xrange(len(declaredFields)):
|
||||
name = declaredFields[i].getName()
|
||||
ret.append(name)
|
||||
found.put(name, 1)
|
||||
|
||||
|
||||
elif isclass(obj.__class__):
|
||||
|
||||
|
||||
elif isclass(obj.__class__):
|
||||
d = dir(obj.__class__)
|
||||
for name in d:
|
||||
ret.append(name)
|
||||
found.put(name, 1)
|
||||
|
||||
|
||||
|
||||
#this simple dir does not always get all the info, that's why we have the part before
|
||||
#(e.g.: if we do a dir on String, some methods that are from other interfaces such as
|
||||
#(e.g.: if we do a dir on String, some methods that are from other interfaces such as
|
||||
#charAt don't appear)
|
||||
d = dir(original)
|
||||
for name in d:
|
||||
if found.get(name) != 1:
|
||||
ret.append(name)
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def formatArg(arg):
|
||||
'''formats an argument to be shown
|
||||
'''
|
||||
|
||||
|
||||
s = str(arg)
|
||||
dot = s.rfind('.')
|
||||
if dot >= 0:
|
||||
s = s[dot + 1:]
|
||||
|
||||
|
||||
s = s.replace(';', '')
|
||||
s = s.replace('[]', 'Array')
|
||||
if len(s) > 0:
|
||||
@@ -364,13 +369,13 @@ def formatArg(arg):
|
||||
s = c + s[1:]
|
||||
|
||||
return s
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def Search(data):
|
||||
'''@return file, line, col
|
||||
'''
|
||||
|
||||
|
||||
data = data.replace('\n', '')
|
||||
if data.endswith('.'):
|
||||
data = data.rstrip('.')
|
||||
@@ -379,8 +384,8 @@ def Search(data):
|
||||
return DoFind(f, mod), foundAs
|
||||
except:
|
||||
return DoFind(f, parent), foundAs
|
||||
|
||||
|
||||
|
||||
|
||||
def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr, filter=lambda name:True):
|
||||
'''
|
||||
@param obj_to_complete: the object from where we should get the completions
|
||||
@@ -391,18 +396,18 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
name, doc, args, type (from the TYPE_* constants)
|
||||
'''
|
||||
ret = []
|
||||
|
||||
|
||||
if dirComps is None:
|
||||
dirComps = dirObj(obj_to_complete)
|
||||
|
||||
|
||||
for d in dirComps:
|
||||
|
||||
if d is None:
|
||||
continue
|
||||
|
||||
|
||||
if not filter(d):
|
||||
continue
|
||||
|
||||
|
||||
args = ''
|
||||
doc = ''
|
||||
retType = TYPE_BUILTIN
|
||||
@@ -421,7 +426,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
#note: this only happens when we add things to the sys.path at runtime, if they are added to the classpath
|
||||
#before the run, everything goes fine.
|
||||
#
|
||||
#The code below ilustrates what I mean...
|
||||
#The code below ilustrates what I mean...
|
||||
#
|
||||
#import sys
|
||||
#sys.path.insert(1, r"C:\bin\eclipse310\plugins\org.junit_3.8.1\junit.jar" )
|
||||
@@ -429,7 +434,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
#import junit.framework
|
||||
#print_ dir(junit.framework) #shows the TestCase class here
|
||||
#
|
||||
#import junit.framework.TestCase
|
||||
#import junit.framework.TestCase
|
||||
#
|
||||
#raises the error:
|
||||
#Traceback (innermost last):
|
||||
@@ -458,19 +463,19 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
|
||||
except TypeError:
|
||||
traceback.print_exc()
|
||||
args = '()'
|
||||
|
||||
|
||||
retType = TYPE_FUNCTION
|
||||
|
||||
|
||||
elif isclass(obj):
|
||||
retType = TYPE_CLASS
|
||||
|
||||
|
||||
elif ismodule(obj):
|
||||
retType = TYPE_IMPORT
|
||||
|
||||
|
||||
#add token and doc to return - assure only strings.
|
||||
ret.append((d, doc, args, retType))
|
||||
|
||||
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
@@ -1,982 +1,14 @@
|
||||
"""Thread module emulating a subset of Java's threading model."""
|
||||
from threading import enumerate, currentThread, Condition, Event, Timer, Thread
|
||||
try:
|
||||
from threading import settrace
|
||||
except:
|
||||
pass
|
||||
|
||||
import sys as _sys
|
||||
|
||||
try:
|
||||
import _pydev_thread as thread
|
||||
except ImportError:
|
||||
import thread
|
||||
|
||||
import warnings
|
||||
|
||||
from _pydev_time import time as _time, sleep as _sleep
|
||||
from traceback import format_exc as _format_exc
|
||||
|
||||
# Note regarding PEP 8 compliant aliases
|
||||
# This threading model was originally inspired by Java, and inherited
|
||||
# the convention of camelCase function and method names from that
|
||||
# language. While those names are not in any imminent danger of being
|
||||
# deprecated, starting with Python 2.6, the module now provides a
|
||||
# PEP 8 compliant alias for any such method name.
|
||||
# Using the new PEP 8 compliant names also facilitates substitution
|
||||
# with the multiprocessing module, which doesn't provide the old
|
||||
# Java inspired names.
|
||||
|
||||
|
||||
# Rename some stuff so "from threading import *" is safe
|
||||
__all__ = ['activeCount', 'active_count', 'Condition', 'currentThread',
|
||||
'current_thread', 'enumerate', 'Event',
|
||||
'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
|
||||
'Timer', 'setprofile', 'settrace', 'local', 'stack_size']
|
||||
|
||||
_start_new_thread = thread.start_new_thread
|
||||
_allocate_lock = thread.allocate_lock
|
||||
_get_ident = thread.get_ident
|
||||
ThreadError = thread.error
|
||||
del thread
|
||||
|
||||
|
||||
# sys.exc_clear is used to work around the fact that except blocks
|
||||
# don't fully clear the exception until 3.0.
|
||||
warnings.filterwarnings('ignore', category=DeprecationWarning,
|
||||
module='threading', message='sys.exc_clear')
|
||||
|
||||
# Debug support (adapted from ihooks.py).
|
||||
# All the major classes here derive from _Verbose. We force that to
|
||||
# be a new-style class so that all the major classes here are new-style.
|
||||
# This helps debugging (type(instance) is more revealing for instances
|
||||
# of new-style classes).
|
||||
|
||||
_VERBOSE = False
|
||||
|
||||
if __debug__:
|
||||
|
||||
class _Verbose(object):
|
||||
|
||||
def __init__(self, verbose=None):
|
||||
if verbose is None:
|
||||
verbose = _VERBOSE
|
||||
self.__verbose = verbose
|
||||
|
||||
def _note(self, format, *args):
|
||||
if self.__verbose:
|
||||
format = format % args
|
||||
# Issue #4188: calling current_thread() can incur an infinite
|
||||
# recursion if it has to create a DummyThread on the fly.
|
||||
ident = _get_ident()
|
||||
try:
|
||||
name = _active[ident].name
|
||||
except KeyError:
|
||||
name = "<OS thread %d>" % ident
|
||||
format = "%s: %s\n" % (name, format)
|
||||
_sys.stderr.write(format)
|
||||
|
||||
else:
|
||||
# Disable this when using "python -O"
|
||||
class _Verbose(object):
|
||||
def __init__(self, verbose=None):
|
||||
pass
|
||||
def _note(self, *args):
|
||||
pass
|
||||
|
||||
# Support for profile and trace hooks
|
||||
|
||||
_profile_hook = None
|
||||
_trace_hook = None
|
||||
|
||||
def setprofile(func):
|
||||
global _profile_hook
|
||||
_profile_hook = func
|
||||
|
||||
def settrace(func):
|
||||
global _trace_hook
|
||||
_trace_hook = func
|
||||
|
||||
# Synchronization classes
|
||||
|
||||
Lock = _allocate_lock
|
||||
|
||||
def RLock(*args, **kwargs):
|
||||
return _RLock(*args, **kwargs)
|
||||
|
||||
class _RLock(_Verbose):
|
||||
|
||||
def __init__(self, verbose=None):
|
||||
_Verbose.__init__(self, verbose)
|
||||
self.__block = _allocate_lock()
|
||||
self.__owner = None
|
||||
self.__count = 0
|
||||
|
||||
def __repr__(self):
|
||||
owner = self.__owner
|
||||
try:
|
||||
owner = _active[owner].name
|
||||
except KeyError:
|
||||
pass
|
||||
return "<%s owner=%r count=%d>" % (
|
||||
self.__class__.__name__, owner, self.__count)
|
||||
|
||||
def acquire(self, blocking=1):
|
||||
me = _get_ident()
|
||||
if self.__owner == me:
|
||||
self.__count = self.__count + 1
|
||||
if __debug__:
|
||||
self._note("%s.acquire(%s): recursive success", self, blocking)
|
||||
return 1
|
||||
rc = self.__block.acquire(blocking)
|
||||
if rc:
|
||||
self.__owner = me
|
||||
self.__count = 1
|
||||
if __debug__:
|
||||
self._note("%s.acquire(%s): initial success", self, blocking)
|
||||
else:
|
||||
if __debug__:
|
||||
self._note("%s.acquire(%s): failure", self, blocking)
|
||||
return rc
|
||||
|
||||
__enter__ = acquire
|
||||
|
||||
def release(self):
|
||||
if self.__owner != _get_ident():
|
||||
raise RuntimeError("cannot release un-acquired lock")
|
||||
self.__count = count = self.__count - 1
|
||||
if not count:
|
||||
self.__owner = None
|
||||
self.__block.release()
|
||||
if __debug__:
|
||||
self._note("%s.release(): final release", self)
|
||||
else:
|
||||
if __debug__:
|
||||
self._note("%s.release(): non-final release", self)
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
self.release()
|
||||
|
||||
# Internal methods used by condition variables
|
||||
|
||||
def _acquire_restore(self, count_owner):
|
||||
count, owner = count_owner
|
||||
self.__block.acquire()
|
||||
self.__count = count
|
||||
self.__owner = owner
|
||||
if __debug__:
|
||||
self._note("%s._acquire_restore()", self)
|
||||
|
||||
def _release_save(self):
|
||||
if __debug__:
|
||||
self._note("%s._release_save()", self)
|
||||
count = self.__count
|
||||
self.__count = 0
|
||||
owner = self.__owner
|
||||
self.__owner = None
|
||||
self.__block.release()
|
||||
return (count, owner)
|
||||
|
||||
def _is_owned(self):
|
||||
return self.__owner == _get_ident()
|
||||
|
||||
|
||||
def Condition(*args, **kwargs):
|
||||
return _Condition(*args, **kwargs)
|
||||
|
||||
class _Condition(_Verbose):
|
||||
|
||||
def __init__(self, lock=None, verbose=None):
|
||||
_Verbose.__init__(self, verbose)
|
||||
if lock is None:
|
||||
lock = RLock()
|
||||
self.__lock = lock
|
||||
# Export the lock's acquire() and release() methods
|
||||
self.acquire = lock.acquire
|
||||
self.release = lock.release
|
||||
# If the lock defines _release_save() and/or _acquire_restore(),
|
||||
# these override the default implementations (which just call
|
||||
# release() and acquire() on the lock). Ditto for _is_owned().
|
||||
try:
|
||||
self._release_save = lock._release_save
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
self._acquire_restore = lock._acquire_restore
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
self._is_owned = lock._is_owned
|
||||
except AttributeError:
|
||||
pass
|
||||
self.__waiters = []
|
||||
|
||||
def __enter__(self):
|
||||
return self.__lock.__enter__()
|
||||
|
||||
def __exit__(self, *args):
|
||||
return self.__lock.__exit__(*args)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters))
|
||||
|
||||
def _release_save(self):
|
||||
self.__lock.release() # No state to save
|
||||
|
||||
def _acquire_restore(self, x):
|
||||
self.__lock.acquire() # Ignore saved state
|
||||
|
||||
def _is_owned(self):
|
||||
# Return True if lock is owned by current_thread.
|
||||
# This method is called only if __lock doesn't have _is_owned().
|
||||
if self.__lock.acquire(0):
|
||||
self.__lock.release()
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def wait(self, timeout=None):
|
||||
if not self._is_owned():
|
||||
raise RuntimeError("cannot wait on un-acquired lock")
|
||||
waiter = _allocate_lock()
|
||||
waiter.acquire()
|
||||
self.__waiters.append(waiter)
|
||||
saved_state = self._release_save()
|
||||
try: # restore state no matter what (e.g., KeyboardInterrupt)
|
||||
if timeout is None:
|
||||
waiter.acquire()
|
||||
if __debug__:
|
||||
self._note("%s.wait(): got it", self)
|
||||
else:
|
||||
# Balancing act: We can't afford a pure busy loop, so we
|
||||
# have to sleep; but if we sleep the whole timeout time,
|
||||
# we'll be unresponsive. The scheme here sleeps very
|
||||
# little at first, longer as time goes on, but never longer
|
||||
# than 20 times per second (or the timeout time remaining).
|
||||
endtime = _time() + timeout
|
||||
delay = 0.0005 # 500 us -> initial delay of 1 ms
|
||||
while True:
|
||||
gotit = waiter.acquire(0)
|
||||
if gotit:
|
||||
break
|
||||
remaining = endtime - _time()
|
||||
if remaining <= 0:
|
||||
break
|
||||
delay = min(delay * 2, remaining, .05)
|
||||
_sleep(delay)
|
||||
if not gotit:
|
||||
if __debug__:
|
||||
self._note("%s.wait(%s): timed out", self, timeout)
|
||||
try:
|
||||
self.__waiters.remove(waiter)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
if __debug__:
|
||||
self._note("%s.wait(%s): got it", self, timeout)
|
||||
finally:
|
||||
self._acquire_restore(saved_state)
|
||||
|
||||
def notify(self, n=1):
|
||||
if not self._is_owned():
|
||||
raise RuntimeError("cannot notify on un-acquired lock")
|
||||
__waiters = self.__waiters
|
||||
waiters = __waiters[:n]
|
||||
if not waiters:
|
||||
if __debug__:
|
||||
self._note("%s.notify(): no waiters", self)
|
||||
return
|
||||
self._note("%s.notify(): notifying %d waiter%s", self, n,
|
||||
n!=1 and "s" or "")
|
||||
for waiter in waiters:
|
||||
waiter.release()
|
||||
try:
|
||||
__waiters.remove(waiter)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def notifyAll(self):
|
||||
self.notify(len(self.__waiters))
|
||||
|
||||
notify_all = notifyAll
|
||||
|
||||
|
||||
def Semaphore(*args, **kwargs):
|
||||
return _Semaphore(*args, **kwargs)
|
||||
|
||||
class _Semaphore(_Verbose):
|
||||
|
||||
# After Tim Peters' semaphore class, but not quite the same (no maximum)
|
||||
|
||||
def __init__(self, value=1, verbose=None):
|
||||
if value < 0:
|
||||
raise ValueError("semaphore initial value must be >= 0")
|
||||
_Verbose.__init__(self, verbose)
|
||||
self.__cond = Condition(Lock())
|
||||
self.__value = value
|
||||
|
||||
def acquire(self, blocking=1):
|
||||
rc = False
|
||||
self.__cond.acquire()
|
||||
while self.__value == 0:
|
||||
if not blocking:
|
||||
break
|
||||
if __debug__:
|
||||
self._note("%s.acquire(%s): blocked waiting, value=%s",
|
||||
self, blocking, self.__value)
|
||||
self.__cond.wait()
|
||||
else:
|
||||
self.__value = self.__value - 1
|
||||
if __debug__:
|
||||
self._note("%s.acquire: success, value=%s",
|
||||
self, self.__value)
|
||||
rc = True
|
||||
self.__cond.release()
|
||||
return rc
|
||||
|
||||
__enter__ = acquire
|
||||
|
||||
def release(self):
|
||||
self.__cond.acquire()
|
||||
self.__value = self.__value + 1
|
||||
if __debug__:
|
||||
self._note("%s.release: success, value=%s",
|
||||
self, self.__value)
|
||||
self.__cond.notify()
|
||||
self.__cond.release()
|
||||
|
||||
def __exit__(self, t, v, tb):
|
||||
self.release()
|
||||
|
||||
|
||||
def BoundedSemaphore(*args, **kwargs):
|
||||
return _BoundedSemaphore(*args, **kwargs)
|
||||
|
||||
class _BoundedSemaphore(_Semaphore):
|
||||
"""Semaphore that checks that # releases is <= # acquires"""
|
||||
def __init__(self, value=1, verbose=None):
|
||||
_Semaphore.__init__(self, value, verbose)
|
||||
self._initial_value = value
|
||||
|
||||
def release(self):
|
||||
if self._Semaphore__value >= self._initial_value:
|
||||
raise ValueError, "Semaphore released too many times"
|
||||
return _Semaphore.release(self)
|
||||
|
||||
|
||||
def Event(*args, **kwargs):
|
||||
return _Event(*args, **kwargs)
|
||||
|
||||
class _Event(_Verbose):
|
||||
|
||||
# After Tim Peters' event class (without is_posted())
|
||||
|
||||
def __init__(self, verbose=None):
|
||||
_Verbose.__init__(self, verbose)
|
||||
self.__cond = Condition(Lock())
|
||||
self.__flag = False
|
||||
|
||||
def _reset_internal_locks(self):
|
||||
# private! called by Thread._reset_internal_locks by _after_fork()
|
||||
self.__cond.__init__()
|
||||
|
||||
def isSet(self):
|
||||
return self.__flag
|
||||
|
||||
is_set = isSet
|
||||
|
||||
def set(self):
|
||||
self.__cond.acquire()
|
||||
try:
|
||||
self.__flag = True
|
||||
self.__cond.notify_all()
|
||||
finally:
|
||||
self.__cond.release()
|
||||
|
||||
def clear(self):
|
||||
self.__cond.acquire()
|
||||
try:
|
||||
self.__flag = False
|
||||
finally:
|
||||
self.__cond.release()
|
||||
|
||||
def wait(self, timeout=None):
|
||||
self.__cond.acquire()
|
||||
try:
|
||||
if not self.__flag:
|
||||
self.__cond.wait(timeout)
|
||||
return self.__flag
|
||||
finally:
|
||||
self.__cond.release()
|
||||
|
||||
# Helper to generate new thread names
|
||||
_counter = 0
|
||||
def _newname(template="Thread-%d"):
|
||||
global _counter
|
||||
_counter = _counter + 1
|
||||
return template % _counter
|
||||
|
||||
# Active thread administration
|
||||
_active_limbo_lock = _allocate_lock()
|
||||
_active = {} # maps thread id to Thread object
|
||||
_limbo = {}
|
||||
|
||||
|
||||
# Main class for threads
|
||||
|
||||
class Thread(_Verbose):
|
||||
|
||||
__initialized = False
|
||||
# Need to store a reference to sys.exc_info for printing
|
||||
# out exceptions when a thread tries to use a global var. during interp.
|
||||
# shutdown and thus raises an exception about trying to perform some
|
||||
# operation on/with a NoneType
|
||||
__exc_info = _sys.exc_info
|
||||
# Keep sys.exc_clear too to clear the exception just before
|
||||
# allowing .join() to return.
|
||||
__exc_clear = _sys.exc_clear
|
||||
|
||||
def __init__(self, group=None, target=None, name=None,
|
||||
args=(), kwargs=None, verbose=None):
|
||||
assert group is None, "group argument must be None for now"
|
||||
_Verbose.__init__(self, verbose)
|
||||
if kwargs is None:
|
||||
kwargs = {}
|
||||
self.__target = target
|
||||
self.__name = str(name or _newname())
|
||||
self.__args = args
|
||||
self.__kwargs = kwargs
|
||||
self.__daemonic = self._set_daemon()
|
||||
self.__ident = None
|
||||
self.__started = Event()
|
||||
self.__stopped = False
|
||||
self.__block = Condition(Lock())
|
||||
self.__initialized = True
|
||||
# sys.stderr is not stored in the class like
|
||||
# sys.exc_info since it can be changed between instances
|
||||
self.__stderr = _sys.stderr
|
||||
|
||||
def _reset_internal_locks(self):
|
||||
# private! Called by _after_fork() to reset our internal locks as
|
||||
# they may be in an invalid state leading to a deadlock or crash.
|
||||
if hasattr(self, '_Thread__block'): # DummyThread deletes self.__block
|
||||
self.__block.__init__()
|
||||
self.__started._reset_internal_locks()
|
||||
|
||||
@property
|
||||
def _block(self):
|
||||
# used by a unittest
|
||||
return self.__block
|
||||
|
||||
def _set_daemon(self):
|
||||
# Overridden in _MainThread and _DummyThread
|
||||
return current_thread().daemon
|
||||
|
||||
def __repr__(self):
|
||||
assert self.__initialized, "Thread.__init__() was not called"
|
||||
status = "initial"
|
||||
if self.__started.is_set():
|
||||
status = "started"
|
||||
if self.__stopped:
|
||||
status = "stopped"
|
||||
if self.__daemonic:
|
||||
status += " daemon"
|
||||
if self.__ident is not None:
|
||||
status += " %s" % self.__ident
|
||||
return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status)
|
||||
|
||||
def start(self):
|
||||
if not self.__initialized:
|
||||
raise RuntimeError("thread.__init__() not called")
|
||||
if self.__started.is_set():
|
||||
raise RuntimeError("threads can only be started once")
|
||||
if __debug__:
|
||||
self._note("%s.start(): starting thread", self)
|
||||
with _active_limbo_lock:
|
||||
_limbo[self] = self
|
||||
try:
|
||||
_start_new_thread(self.__bootstrap, ())
|
||||
except Exception:
|
||||
with _active_limbo_lock:
|
||||
del _limbo[self]
|
||||
raise
|
||||
self.__started.wait()
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
if self.__target:
|
||||
self.__target(*self.__args, **self.__kwargs)
|
||||
finally:
|
||||
# Avoid a refcycle if the thread is running a function with
|
||||
# an argument that has a member that points to the thread.
|
||||
del self.__target, self.__args, self.__kwargs
|
||||
|
||||
def __bootstrap(self):
|
||||
# Wrapper around the real bootstrap code that ignores
|
||||
# exceptions during interpreter cleanup. Those typically
|
||||
# happen when a daemon thread wakes up at an unfortunate
|
||||
# moment, finds the world around it destroyed, and raises some
|
||||
# random exception *** while trying to report the exception in
|
||||
# __bootstrap_inner() below ***. Those random exceptions
|
||||
# don't help anybody, and they confuse users, so we suppress
|
||||
# them. We suppress them only when it appears that the world
|
||||
# indeed has already been destroyed, so that exceptions in
|
||||
# __bootstrap_inner() during normal business hours are properly
|
||||
# reported. Also, we only suppress them for daemonic threads;
|
||||
# if a non-daemonic encounters this, something else is wrong.
|
||||
try:
|
||||
self.__bootstrap_inner()
|
||||
except:
|
||||
if self.__daemonic and _sys is None:
|
||||
return
|
||||
raise
|
||||
|
||||
def _set_ident(self):
|
||||
self.__ident = _get_ident()
|
||||
|
||||
def __bootstrap_inner(self):
|
||||
try:
|
||||
self._set_ident()
|
||||
self.__started.set()
|
||||
with _active_limbo_lock:
|
||||
_active[self.__ident] = self
|
||||
del _limbo[self]
|
||||
if __debug__:
|
||||
self._note("%s.__bootstrap(): thread started", self)
|
||||
|
||||
if _trace_hook:
|
||||
self._note("%s.__bootstrap(): registering trace hook", self)
|
||||
_sys.settrace(_trace_hook)
|
||||
if _profile_hook:
|
||||
self._note("%s.__bootstrap(): registering profile hook", self)
|
||||
_sys.setprofile(_profile_hook)
|
||||
|
||||
try:
|
||||
self.run()
|
||||
except SystemExit:
|
||||
if __debug__:
|
||||
self._note("%s.__bootstrap(): raised SystemExit", self)
|
||||
except:
|
||||
if __debug__:
|
||||
self._note("%s.__bootstrap(): unhandled exception", self)
|
||||
# If sys.stderr is no more (most likely from interpreter
|
||||
# shutdown) use self.__stderr. Otherwise still use sys (as in
|
||||
# _sys) in case sys.stderr was redefined since the creation of
|
||||
# self.
|
||||
if _sys:
|
||||
_sys.stderr.write("Exception in thread %s:\n%s\n" %
|
||||
(self.name, _format_exc()))
|
||||
else:
|
||||
# Do the best job possible w/o a huge amt. of code to
|
||||
# approximate a traceback (code ideas from
|
||||
# Lib/traceback.py)
|
||||
exc_type, exc_value, exc_tb = self.__exc_info()
|
||||
try:
|
||||
print>>self.__stderr, (
|
||||
"Exception in thread " + self.name +
|
||||
" (most likely raised during interpreter shutdown):")
|
||||
print>>self.__stderr, (
|
||||
"Traceback (most recent call last):")
|
||||
while exc_tb:
|
||||
print>>self.__stderr, (
|
||||
' File "%s", line %s, in %s' %
|
||||
(exc_tb.tb_frame.f_code.co_filename,
|
||||
exc_tb.tb_lineno,
|
||||
exc_tb.tb_frame.f_code.co_name))
|
||||
exc_tb = exc_tb.tb_next
|
||||
print>>self.__stderr, ("%s: %s" % (exc_type, exc_value))
|
||||
# Make sure that exc_tb gets deleted since it is a memory
|
||||
# hog; deleting everything else is just for thoroughness
|
||||
finally:
|
||||
del exc_type, exc_value, exc_tb
|
||||
else:
|
||||
if __debug__:
|
||||
self._note("%s.__bootstrap(): normal return", self)
|
||||
finally:
|
||||
# Prevent a race in
|
||||
# test_threading.test_no_refcycle_through_target when
|
||||
# the exception keeps the target alive past when we
|
||||
# assert that it's dead.
|
||||
self.__exc_clear()
|
||||
finally:
|
||||
with _active_limbo_lock:
|
||||
self.__stop()
|
||||
try:
|
||||
# We don't call self.__delete() because it also
|
||||
# grabs _active_limbo_lock.
|
||||
del _active[_get_ident()]
|
||||
except:
|
||||
pass
|
||||
|
||||
def __stop(self):
|
||||
self.__block.acquire()
|
||||
self.__stopped = True
|
||||
self.__block.notify_all()
|
||||
self.__block.release()
|
||||
|
||||
def __delete(self):
|
||||
"Remove current thread from the dict of currently running threads."
|
||||
|
||||
# Notes about running with dummy_thread:
|
||||
#
|
||||
# Must take care to not raise an exception if dummy_thread is being
|
||||
# used (and thus this module is being used as an instance of
|
||||
# dummy_threading). dummy_thread.get_ident() always returns -1 since
|
||||
# there is only one thread if dummy_thread is being used. Thus
|
||||
# len(_active) is always <= 1 here, and any Thread instance created
|
||||
# overwrites the (if any) thread currently registered in _active.
|
||||
#
|
||||
# An instance of _MainThread is always created by 'threading'. This
|
||||
# gets overwritten the instant an instance of Thread is created; both
|
||||
# threads return -1 from dummy_thread.get_ident() and thus have the
|
||||
# same key in the dict. So when the _MainThread instance created by
|
||||
# 'threading' tries to clean itself up when atexit calls this method
|
||||
# it gets a KeyError if another Thread instance was created.
|
||||
#
|
||||
# This all means that KeyError from trying to delete something from
|
||||
# _active if dummy_threading is being used is a red herring. But
|
||||
# since it isn't if dummy_threading is *not* being used then don't
|
||||
# hide the exception.
|
||||
|
||||
try:
|
||||
with _active_limbo_lock:
|
||||
del _active[_get_ident()]
|
||||
# There must not be any python code between the previous line
|
||||
# and after the lock is released. Otherwise a tracing function
|
||||
# could try to acquire the lock again in the same thread, (in
|
||||
# current_thread()), and would block.
|
||||
except KeyError:
|
||||
if 'dummy_threading' not in _sys.modules:
|
||||
raise
|
||||
|
||||
def join(self, timeout=None):
|
||||
if not self.__initialized:
|
||||
raise RuntimeError("Thread.__init__() not called")
|
||||
if not self.__started.is_set():
|
||||
raise RuntimeError("cannot join thread before it is started")
|
||||
if self is current_thread():
|
||||
raise RuntimeError("cannot join current thread")
|
||||
|
||||
if __debug__:
|
||||
if not self.__stopped:
|
||||
self._note("%s.join(): waiting until thread stops", self)
|
||||
self.__block.acquire()
|
||||
try:
|
||||
if timeout is None:
|
||||
while not self.__stopped:
|
||||
self.__block.wait()
|
||||
if __debug__:
|
||||
self._note("%s.join(): thread stopped", self)
|
||||
else:
|
||||
deadline = _time() + timeout
|
||||
while not self.__stopped:
|
||||
delay = deadline - _time()
|
||||
if delay <= 0:
|
||||
if __debug__:
|
||||
self._note("%s.join(): timed out", self)
|
||||
break
|
||||
self.__block.wait(delay)
|
||||
else:
|
||||
if __debug__:
|
||||
self._note("%s.join(): thread stopped", self)
|
||||
finally:
|
||||
self.__block.release()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
assert self.__initialized, "Thread.__init__() not called"
|
||||
return self.__name
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
assert self.__initialized, "Thread.__init__() not called"
|
||||
self.__name = str(name)
|
||||
|
||||
@property
|
||||
def ident(self):
|
||||
assert self.__initialized, "Thread.__init__() not called"
|
||||
return self.__ident
|
||||
|
||||
def isAlive(self):
|
||||
assert self.__initialized, "Thread.__init__() not called"
|
||||
return self.__started.is_set() and not self.__stopped
|
||||
|
||||
is_alive = isAlive
|
||||
|
||||
@property
|
||||
def daemon(self):
|
||||
assert self.__initialized, "Thread.__init__() not called"
|
||||
return self.__daemonic
|
||||
|
||||
@daemon.setter
|
||||
def daemon(self, daemonic):
|
||||
if not self.__initialized:
|
||||
raise RuntimeError("Thread.__init__() not called")
|
||||
if self.__started.is_set():
|
||||
raise RuntimeError("cannot set daemon status of active thread");
|
||||
self.__daemonic = daemonic
|
||||
|
||||
def isDaemon(self):
|
||||
return self.daemon
|
||||
|
||||
def setDaemon(self, daemonic):
|
||||
self.daemon = daemonic
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def setName(self, name):
|
||||
self.name = name
|
||||
|
||||
# The timer class was contributed by Itamar Shtull-Trauring
|
||||
|
||||
def Timer(*args, **kwargs):
|
||||
return _Timer(*args, **kwargs)
|
||||
|
||||
class _Timer(Thread):
|
||||
"""Call a function after a specified number of seconds:
|
||||
|
||||
t = Timer(30.0, f, args=[], kwargs={})
|
||||
t.start()
|
||||
t.cancel() # stop the timer's action if it's still waiting
|
||||
"""
|
||||
|
||||
def __init__(self, interval, function, args=[], kwargs={}):
|
||||
Thread.__init__(self)
|
||||
self.interval = interval
|
||||
self.function = function
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.finished = Event()
|
||||
|
||||
def cancel(self):
|
||||
"""Stop the timer if it hasn't finished yet"""
|
||||
self.finished.set()
|
||||
|
||||
def run(self):
|
||||
self.finished.wait(self.interval)
|
||||
if not self.finished.is_set():
|
||||
self.function(*self.args, **self.kwargs)
|
||||
self.finished.set()
|
||||
|
||||
# Special thread class to represent the main thread
|
||||
# This is garbage collected through an exit handler
|
||||
|
||||
class _MainThread(Thread):
|
||||
|
||||
def __init__(self):
|
||||
Thread.__init__(self, name="MainThread")
|
||||
self._Thread__started.set()
|
||||
self._set_ident()
|
||||
with _active_limbo_lock:
|
||||
_active[_get_ident()] = self
|
||||
|
||||
def _set_daemon(self):
|
||||
return False
|
||||
|
||||
def _exitfunc(self):
|
||||
self._Thread__stop()
|
||||
t = _pickSomeNonDaemonThread()
|
||||
if t:
|
||||
if __debug__:
|
||||
self._note("%s: waiting for other threads", self)
|
||||
while t:
|
||||
t.join()
|
||||
t = _pickSomeNonDaemonThread()
|
||||
if __debug__:
|
||||
self._note("%s: exiting", self)
|
||||
self._Thread__delete()
|
||||
|
||||
def _pickSomeNonDaemonThread():
|
||||
for t in enumerate():
|
||||
if not t.daemon and t.is_alive():
|
||||
return t
|
||||
return None
|
||||
|
||||
|
||||
# Dummy thread class to represent threads not started here.
|
||||
# These aren't garbage collected when they die, nor can they be waited for.
|
||||
# If they invoke anything in threading.py that calls current_thread(), they
|
||||
# leave an entry in the _active dict forever after.
|
||||
# Their purpose is to return *something* from current_thread().
|
||||
# They are marked as daemon threads so we won't wait for them
|
||||
# when we exit (conform previous semantics).
|
||||
|
||||
class _DummyThread(Thread):
|
||||
|
||||
def __init__(self):
|
||||
Thread.__init__(self, name=_newname("Dummy-%d"))
|
||||
|
||||
# Thread.__block consumes an OS-level locking primitive, which
|
||||
# can never be used by a _DummyThread. Since a _DummyThread
|
||||
# instance is immortal, that's bad, so release this resource.
|
||||
del self._Thread__block
|
||||
|
||||
self._Thread__started.set()
|
||||
self._set_ident()
|
||||
with _active_limbo_lock:
|
||||
_active[_get_ident()] = self
|
||||
|
||||
def _set_daemon(self):
|
||||
return True
|
||||
|
||||
def join(self, timeout=None):
|
||||
assert False, "cannot join a dummy thread"
|
||||
|
||||
|
||||
# Global API functions
|
||||
|
||||
def currentThread():
|
||||
try:
|
||||
return _active[_get_ident()]
|
||||
except KeyError:
|
||||
##print "current_thread(): no current thread for", _get_ident()
|
||||
return _DummyThread()
|
||||
|
||||
current_thread = currentThread
|
||||
|
||||
def activeCount():
|
||||
with _active_limbo_lock:
|
||||
return len(_active) + len(_limbo)
|
||||
|
||||
active_count = activeCount
|
||||
|
||||
def _enumerate():
|
||||
# Same as enumerate(), but without the lock. Internal use only.
|
||||
return _active.values() + _limbo.values()
|
||||
|
||||
def enumerate():
|
||||
with _active_limbo_lock:
|
||||
return _active.values() + _limbo.values()
|
||||
|
||||
# Create the main thread object,
|
||||
# and make it available for the interpreter
|
||||
# (Py_Main) as threading._shutdown.
|
||||
|
||||
_shutdown = _MainThread()._exitfunc
|
||||
|
||||
# get thread-local implementation, either from the thread
|
||||
# module, or from the python fallback
|
||||
|
||||
try:
|
||||
from _pydev_thread import _local as local
|
||||
except ImportError:
|
||||
from _threading_local import local
|
||||
|
||||
|
||||
def _after_fork():
|
||||
# This function is called by Python/ceval.c:PyEval_ReInitThreads which
|
||||
# is called from PyOS_AfterFork. Here we cleanup threading module state
|
||||
# that should not exist after a fork.
|
||||
|
||||
# Reset _active_limbo_lock, in case we forked while the lock was held
|
||||
# by another (non-forked) thread. http://bugs.python.org/issue874900
|
||||
global _active_limbo_lock
|
||||
_active_limbo_lock = _allocate_lock()
|
||||
|
||||
# fork() only copied the current thread; clear references to others.
|
||||
new_active = {}
|
||||
current = current_thread()
|
||||
with _active_limbo_lock:
|
||||
for thread in _active.itervalues():
|
||||
# Any lock/condition variable may be currently locked or in an
|
||||
# invalid state, so we reinitialize them.
|
||||
if hasattr(thread, '_reset_internal_locks'):
|
||||
thread._reset_internal_locks()
|
||||
if thread is current:
|
||||
# There is only one active thread. We reset the ident to
|
||||
# its new value since it can have changed.
|
||||
ident = _get_ident()
|
||||
thread._Thread__ident = ident
|
||||
new_active[ident] = thread
|
||||
else:
|
||||
# All the others are already stopped.
|
||||
thread._Thread__stop()
|
||||
|
||||
_limbo.clear()
|
||||
_active.clear()
|
||||
_active.update(new_active)
|
||||
assert len(_active) == 1
|
||||
|
||||
|
||||
# Self-test code
|
||||
|
||||
def _test():
|
||||
|
||||
class BoundedQueue(_Verbose):
|
||||
|
||||
def __init__(self, limit):
|
||||
_Verbose.__init__(self)
|
||||
self.mon = RLock()
|
||||
self.rc = Condition(self.mon)
|
||||
self.wc = Condition(self.mon)
|
||||
self.limit = limit
|
||||
self.queue = deque()
|
||||
|
||||
def put(self, item):
|
||||
self.mon.acquire()
|
||||
while len(self.queue) >= self.limit:
|
||||
self._note("put(%s): queue full", item)
|
||||
self.wc.wait()
|
||||
self.queue.append(item)
|
||||
self._note("put(%s): appended, length now %d",
|
||||
item, len(self.queue))
|
||||
self.rc.notify()
|
||||
self.mon.release()
|
||||
|
||||
def get(self):
|
||||
self.mon.acquire()
|
||||
while not self.queue:
|
||||
self._note("get(): queue empty")
|
||||
self.rc.wait()
|
||||
item = self.queue.popleft()
|
||||
self._note("get(): got %s, %d left", item, len(self.queue))
|
||||
self.wc.notify()
|
||||
self.mon.release()
|
||||
return item
|
||||
|
||||
class ProducerThread(Thread):
|
||||
|
||||
def __init__(self, queue, quota):
|
||||
Thread.__init__(self, name="Producer")
|
||||
self.queue = queue
|
||||
self.quota = quota
|
||||
|
||||
def run(self):
|
||||
from random import random
|
||||
counter = 0
|
||||
while counter < self.quota:
|
||||
counter = counter + 1
|
||||
self.queue.put("%s.%d" % (self.name, counter))
|
||||
_sleep(random() * 0.00001)
|
||||
|
||||
|
||||
class ConsumerThread(Thread):
|
||||
|
||||
def __init__(self, queue, count):
|
||||
Thread.__init__(self, name="Consumer")
|
||||
self.queue = queue
|
||||
self.count = count
|
||||
|
||||
def run(self):
|
||||
while self.count > 0:
|
||||
item = self.queue.get()
|
||||
print item
|
||||
self.count = self.count - 1
|
||||
|
||||
NP = 3
|
||||
QL = 4
|
||||
NI = 5
|
||||
|
||||
Q = BoundedQueue(QL)
|
||||
P = []
|
||||
for i in range(NP):
|
||||
t = ProducerThread(Q, NI)
|
||||
t.name = ("Producer-%d" % (i+1))
|
||||
P.append(t)
|
||||
C = ConsumerThread(Q, NI*NP)
|
||||
for t in P:
|
||||
t.start()
|
||||
_sleep(0.000001)
|
||||
C.start()
|
||||
for t in P:
|
||||
t.join()
|
||||
C.join()
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
from gevent import monkey
|
||||
saved = monkey.saved['threading']
|
||||
for key, val in saved.items():
|
||||
globals()[key] = val
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -2,7 +2,7 @@ try:
|
||||
import inspect
|
||||
except:
|
||||
try:
|
||||
import _pydev_inspect as inspect # for older versions
|
||||
from _pydev_imps import _pydev_inspect as inspect
|
||||
except:
|
||||
import traceback;traceback.print_exc() #Ok, no inspect available (search will not work)
|
||||
|
||||
@@ -10,57 +10,58 @@ try:
|
||||
import re
|
||||
except:
|
||||
try:
|
||||
import _pydev_re as re # for older versions @UnresolvedImport
|
||||
import sre as re # for older versions
|
||||
except:
|
||||
import traceback;traceback.print_exc() #Ok, no inspect available (search will not work)
|
||||
|
||||
|
||||
from pydevd_constants import xrange
|
||||
|
||||
def DoFind(f, mod):
|
||||
import linecache
|
||||
if inspect.ismodule(mod):
|
||||
return f, 0, 0
|
||||
|
||||
|
||||
lines = linecache.getlines(f)
|
||||
|
||||
|
||||
if inspect.isclass(mod):
|
||||
name = mod.__name__
|
||||
pat = re.compile(r'^\s*class\s*' + name + r'\b')
|
||||
for i in range(len(lines)):
|
||||
if pat.match(lines[i]):
|
||||
for i in xrange(len(lines)):
|
||||
if pat.match(lines[i]):
|
||||
return f, i, 0
|
||||
|
||||
|
||||
return f, 0, 0
|
||||
|
||||
if inspect.ismethod(mod):
|
||||
mod = mod.im_func
|
||||
|
||||
|
||||
if inspect.isfunction(mod):
|
||||
try:
|
||||
mod = mod.func_code
|
||||
except AttributeError:
|
||||
mod = mod.__code__ #python 3k
|
||||
|
||||
|
||||
if inspect.istraceback(mod):
|
||||
mod = mod.tb_frame
|
||||
|
||||
|
||||
if inspect.isframe(mod):
|
||||
mod = mod.f_code
|
||||
|
||||
if inspect.iscode(mod):
|
||||
if not hasattr(mod, 'co_filename'):
|
||||
return None, 0, 0
|
||||
|
||||
|
||||
if not hasattr(mod, 'co_firstlineno'):
|
||||
return mod.co_filename, 0, 0
|
||||
|
||||
|
||||
lnum = mod.co_firstlineno
|
||||
pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
|
||||
while lnum > 0:
|
||||
if pat.match(lines[lnum]):
|
||||
if pat.match(lines[lnum]):
|
||||
break
|
||||
lnum -= 1
|
||||
|
||||
|
||||
return f, lnum, 0
|
||||
|
||||
raise RuntimeError('Do not know about: ' + f + ' ' + str(mod))
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
def fixGetpass():
|
||||
import getpass
|
||||
import warnings
|
||||
fallback = getattr(getpass, 'fallback_getpass', None) # >= 2.6
|
||||
if not fallback:
|
||||
fallback = getpass.default_getpass # <= 2.5
|
||||
getpass.getpass = fallback
|
||||
if hasattr(getpass, 'GetPassWarning'):
|
||||
warnings.simplefilter("ignore", category=getpass.GetPassWarning)
|
||||
try:
|
||||
import getpass
|
||||
except ImportError:
|
||||
return #If we can't import it, we can't fix it
|
||||
import warnings
|
||||
fallback = getattr(getpass, 'fallback_getpass', None) # >= 2.6
|
||||
if not fallback:
|
||||
fallback = getpass.default_getpass # <= 2.5
|
||||
getpass.getpass = fallback
|
||||
if hasattr(getpass, 'GetPassWarning'):
|
||||
warnings.simplefilter("ignore", category=getpass.GetPassWarning)
|
||||
|
||||
|
||||
@@ -35,6 +35,25 @@ Done in the merge (started from the PyCharm version and bringing in things from
|
||||
|
||||
- When the code is interrupted, the buffer in the python side is cleared.
|
||||
|
||||
- GEvent debugging: improved PyDev not to use the threading module (uses the thread
|
||||
primitives directly), so, gevent debugging can work even if pydevd is used for
|
||||
remote debugging.
|
||||
|
||||
Also, the gevent debugging should probably be closer to the stackless debugging,
|
||||
where we actually show the live stackless threads -- so, we should show the live
|
||||
gevent greenlets -- which the current version doesn't do (future work).
|
||||
|
||||
- Supporting Jython 2.2 onwards (note: CPython only tested with 2.7/3.3)
|
||||
|
||||
- When there are big sets/tuples/lists/dicts, the items won't be all shown so that the
|
||||
debugger speed doesn't suffer (the user should use the console if he wants to see
|
||||
those items in this case). The limit was set to show up to 300 items (pydevd_resolver.MAX_ITEMS_TO_HANDLE)
|
||||
|
||||
- Monkey-patching qt (QThread/QRunnable) to enable the debugger to work.
|
||||
Notes:
|
||||
- It must be imported before the user actually runs its code (as the definitions of QThread/QRunnable
|
||||
are monkey-patched), so, for the remote debugger to work, pydevd must be imported at the start of
|
||||
the program, even if pydevd.settrace will only be used later on.
|
||||
|
||||
Things to be fixed in PyCharm:
|
||||
--------------------------------
|
||||
@@ -110,27 +129,14 @@ Things to be fixed in PyCharm:
|
||||
Things to be fixed in PyDev:
|
||||
--------------------------------
|
||||
|
||||
1. Provide UI for 'smart step into'
|
||||
.Provide UI for 'smart step into' (later)
|
||||
|
||||
2. Check what to do with 'message' from xml.
|
||||
. Check what to do with 'message' from xml (later)
|
||||
|
||||
3. Enable/test GEvent debugging (environment variable: GEVENT_SUPPORT).
|
||||
. Deal with sendSignatureCallTrace (later)
|
||||
|
||||
4. Deal with sendSignatureCallTrace.
|
||||
. Set IPYTHONENABLE to False/True to use IPython console (later)
|
||||
|
||||
5. Work with Django exceptions: CMD_ADD_DJANGO_EXCEPTION_BREAK/CMD_REMOVE_DJANGO_EXCEPTION_BREAK.
|
||||
|
||||
6. Check console in debug frame.
|
||||
|
||||
7. Set IPYTHONENABLE to False/True to use IPython console.
|
||||
|
||||
TODO:
|
||||
--------
|
||||
sendSignatureCallTrace: don't call if not needed
|
||||
|
||||
Console integration (IPython and 'regular') (interrupt)
|
||||
|
||||
Add back: CMD_EVALUATE_CONSOLE_EXPRESSION
|
||||
|
||||
Manual test:
|
||||
---------------
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
'''
|
||||
@author Radim Kubacki
|
||||
'''
|
||||
import __builtin__
|
||||
import _pydev_imports_tipper
|
||||
import traceback
|
||||
import StringIO
|
||||
import sys
|
||||
import time
|
||||
import urllib
|
||||
import pycompletionserver
|
||||
|
||||
@@ -24,7 +22,7 @@ def GetImports(module_name):
|
||||
except:
|
||||
s = StringIO.StringIO()
|
||||
exc_info = sys.exc_info()
|
||||
|
||||
|
||||
traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], limit=None, file=s)
|
||||
err = s.getvalue()
|
||||
pycompletionserver.dbg('Received error: ' + str(err), pycompletionserver.ERROR)
|
||||
@@ -38,4 +36,4 @@ if __name__ == '__main__':
|
||||
mod_name = sys.argv[1]
|
||||
|
||||
print(GetImports(mod_name))
|
||||
|
||||
|
||||
|
||||
@@ -17,30 +17,21 @@ except NameError:
|
||||
setattr(__builtin__, 'True', 1) # Python 3.0 does not accept __builtin__.True = 1 in its syntax
|
||||
setattr(__builtin__, 'False', 0)
|
||||
|
||||
import pydevd_constants
|
||||
from pydevd_constants import IS_JYTHON
|
||||
|
||||
try:
|
||||
from java.lang import Thread
|
||||
IS_JYTHON = True
|
||||
if IS_JYTHON:
|
||||
import java.lang
|
||||
SERVER_NAME = 'jycompletionserver'
|
||||
import _pydev_jy_imports_tipper # as _pydev_imports_tipper #changed to be backward compatible with 1.5
|
||||
_pydev_imports_tipper = _pydev_jy_imports_tipper
|
||||
|
||||
except ImportError:
|
||||
else:
|
||||
# it is python
|
||||
IS_JYTHON = False
|
||||
SERVER_NAME = 'pycompletionserver'
|
||||
if pydevd_constants.USE_LIB_COPY:
|
||||
from _pydev_threading import Thread
|
||||
else:
|
||||
from threading import Thread
|
||||
import _pydev_imports_tipper
|
||||
|
||||
|
||||
if pydevd_constants.USE_LIB_COPY:
|
||||
import _pydev_socket as socket
|
||||
else:
|
||||
import socket
|
||||
from _pydev_imps import _pydev_socket as socket
|
||||
|
||||
import sys
|
||||
if sys.platform == "darwin":
|
||||
@@ -65,10 +56,7 @@ for name, mod in sys.modules.items():
|
||||
|
||||
import traceback
|
||||
|
||||
if pydevd_constants.USE_LIB_COPY:
|
||||
import _pydev_time as time
|
||||
else:
|
||||
import time
|
||||
from _pydev_imps import _pydev_time as time
|
||||
|
||||
try:
|
||||
import StringIO
|
||||
@@ -93,7 +81,7 @@ def dbg(s, prior):
|
||||
# f = open('c:/temp/test.txt', 'a')
|
||||
# print_ >> f, s
|
||||
# f.close()
|
||||
|
||||
|
||||
import pydev_localhost
|
||||
HOST = pydev_localhost.get_localhost() # Symbolic name meaning the local host
|
||||
|
||||
@@ -191,19 +179,21 @@ class Processor:
|
||||
|
||||
return '%s(%s)%s' % (MSG_COMPLETIONS, ''.join(compMsg), MSG_END)
|
||||
|
||||
class Exit(Exception):
|
||||
pass
|
||||
|
||||
class T(Thread):
|
||||
class CompletionServer:
|
||||
|
||||
def __init__(self, port):
|
||||
Thread.__init__(self)
|
||||
self.ended = False
|
||||
self.port = port
|
||||
self.socket = None # socket to send messages.
|
||||
self.exit_process_on_kill = True
|
||||
self.processor = Processor()
|
||||
|
||||
|
||||
def connectToServer(self):
|
||||
import socket
|
||||
from _pydev_imps import _pydev_socket as socket
|
||||
|
||||
self.socket = s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
@@ -272,7 +262,7 @@ class T(Thread):
|
||||
while data.find(MSG_END) == -1:
|
||||
received = self.socket.recv(BUFFER_SIZE)
|
||||
if len(received) == 0:
|
||||
sys.exit(0) # ok, connection ended
|
||||
raise Exit() # ok, connection ended
|
||||
if IS_PYTHON3K:
|
||||
data = data + received.decode('utf-8')
|
||||
else:
|
||||
@@ -284,7 +274,7 @@ class T(Thread):
|
||||
dbg(SERVER_NAME + ' kill message received', INFO1)
|
||||
# break if we received kill message.
|
||||
self.ended = True
|
||||
sys.exit(0)
|
||||
raise Exit()
|
||||
|
||||
dbg(SERVER_NAME + ' starting keep alive thread', INFO2)
|
||||
|
||||
@@ -365,7 +355,7 @@ class T(Thread):
|
||||
|
||||
else:
|
||||
self.send(MSG_INVALID_REQUEST)
|
||||
except SystemExit:
|
||||
except Exit:
|
||||
self.send(self.getCompletionsMessage(None, [('Exit:', 'SystemExit', '')]))
|
||||
raise
|
||||
|
||||
@@ -384,11 +374,12 @@ class T(Thread):
|
||||
|
||||
self.socket.close()
|
||||
self.ended = True
|
||||
sys.exit(0) # connection broken
|
||||
raise Exit() # connection broken
|
||||
|
||||
|
||||
except SystemExit:
|
||||
raise
|
||||
except Exit:
|
||||
if self.exit_process_on_kill:
|
||||
sys.exit(0)
|
||||
# No need to log SystemExit error
|
||||
except:
|
||||
s = StringIO.StringIO()
|
||||
@@ -405,8 +396,6 @@ if __name__ == '__main__':
|
||||
|
||||
port = int(sys.argv[1]) # this is from where we want to receive messages.
|
||||
|
||||
t = T(port)
|
||||
t = CompletionServer(port)
|
||||
dbg(SERVER_NAME + ' will start', INFO1)
|
||||
t.start()
|
||||
time.sleep(5)
|
||||
t.join()
|
||||
t.run()
|
||||
|
||||
@@ -1,36 +1,11 @@
|
||||
from pydev_imports import xmlrpclib
|
||||
from pydev_imports import xmlrpclib, _queue, Exec
|
||||
import sys
|
||||
|
||||
import traceback
|
||||
|
||||
from pydevd_constants import USE_LIB_COPY
|
||||
from pydevd_constants import IS_JYTHON
|
||||
|
||||
try:
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_Queue as _queue
|
||||
else:
|
||||
import Queue as _queue
|
||||
except:
|
||||
import queue as _queue
|
||||
|
||||
try:
|
||||
from pydevd_exec import Exec
|
||||
except:
|
||||
from pydevd_exec2 import Exec
|
||||
|
||||
try:
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_thread as thread
|
||||
else:
|
||||
import thread
|
||||
except:
|
||||
import _thread as thread
|
||||
|
||||
from _pydev_imps import _pydev_thread as thread
|
||||
import pydevd_xml
|
||||
import pydevd_vars
|
||||
|
||||
from pydevd_utils import *
|
||||
from pydevd_utils import * # @UnusedWildImport
|
||||
import traceback
|
||||
|
||||
#=======================================================================================================================
|
||||
# Null
|
||||
@@ -212,8 +187,6 @@ class BaseInterpreterInterface:
|
||||
self._input_error_printed = True
|
||||
sys.stderr.write('\nError when trying to update pydoc.help.input\n')
|
||||
sys.stderr.write('(help() may not work -- please report this as a bug in the pydev bugtracker).\n\n')
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
|
||||
try:
|
||||
@@ -244,8 +217,6 @@ class BaseInterpreterInterface:
|
||||
except SystemExit:
|
||||
raise
|
||||
except:
|
||||
import traceback;
|
||||
|
||||
traceback.print_exc()
|
||||
|
||||
return more
|
||||
@@ -375,7 +346,7 @@ class BaseInterpreterInterface:
|
||||
self.interruptable = True
|
||||
|
||||
def get_server(self):
|
||||
if self.host is not None:
|
||||
if getattr(self, 'host', None) is not None:
|
||||
return xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port))
|
||||
else:
|
||||
return None
|
||||
@@ -420,7 +391,7 @@ class BaseInterpreterInterface:
|
||||
|
||||
# Important: it has to be really enabled in the main thread, so, schedule
|
||||
# it to run in the main thread.
|
||||
self.exec_queue.put(do_connect_to_debugger)
|
||||
self.exec_queue.put(do_change_variable)
|
||||
|
||||
def _findFrame(self, thread_id, frame_id):
|
||||
'''
|
||||
@@ -446,15 +417,11 @@ class BaseInterpreterInterface:
|
||||
try:
|
||||
# Try to import the packages needed to attach the debugger
|
||||
import pydevd
|
||||
import pydevd_vars
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
import _pydev_threading as threading
|
||||
|
||||
except:
|
||||
# This happens on Jython embedded in host eclipse
|
||||
import traceback;traceback.print_exc()
|
||||
traceback.print_exc()
|
||||
sys.stderr.write('pydevd is not available, cannot connect\n',)
|
||||
|
||||
import pydev_localhost
|
||||
@@ -470,7 +437,7 @@ class BaseInterpreterInterface:
|
||||
import pydevd_tracing
|
||||
pydevd_tracing.SetTrace(None)
|
||||
except:
|
||||
import traceback;traceback.print_exc()
|
||||
traceback.print_exc()
|
||||
sys.stderr.write('Failed to connect to target debugger.\n')
|
||||
|
||||
# Register to process commands when idle
|
||||
@@ -479,7 +446,7 @@ class BaseInterpreterInterface:
|
||||
import pydevconsole
|
||||
pydevconsole.set_debug_hook(self.debugger.processInternalCommands)
|
||||
except:
|
||||
import traceback;traceback.print_exc()
|
||||
traceback.print_exc()
|
||||
sys.stderr.write('Version of Python does not support debuggable Interactive Console.\n')
|
||||
|
||||
# Important: it has to be really enabled in the main thread, so, schedule
|
||||
@@ -505,7 +472,7 @@ class BaseInterpreterInterface:
|
||||
enable_gui(guiname)
|
||||
except:
|
||||
sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname)
|
||||
import traceback;traceback.print_exc()
|
||||
traceback.print_exc()
|
||||
elif guiname not in ['none', '', None]:
|
||||
# Only print a warning if the guiname was going to do something
|
||||
sys.stderr.write("PyDev console: Python version does not support GUI event loop integration for '%s'\n" % guiname)
|
||||
|
||||
@@ -1,49 +1,61 @@
|
||||
from pydevd_constants import USE_LIB_COPY
|
||||
from pydevd_constants import USE_LIB_COPY, izip
|
||||
|
||||
|
||||
try:
|
||||
try:
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_xmlrpclib as xmlrpclib
|
||||
from _pydev_imps import _pydev_xmlrpclib as xmlrpclib
|
||||
else:
|
||||
import xmlrpclib
|
||||
except ImportError:
|
||||
import xmlrpc.client as xmlrpclib
|
||||
except ImportError:
|
||||
import _pydev_xmlrpclib as xmlrpclib
|
||||
from _pydev_imps import _pydev_xmlrpclib as xmlrpclib
|
||||
|
||||
|
||||
try:
|
||||
try:
|
||||
if USE_LIB_COPY:
|
||||
from _pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
|
||||
from _pydev_imps._pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
|
||||
else:
|
||||
from SimpleXMLRPCServer import SimpleXMLRPCServer
|
||||
except ImportError:
|
||||
from xmlrpc.server import SimpleXMLRPCServer
|
||||
except ImportError:
|
||||
from _pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
|
||||
from _pydev_imps._pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
|
||||
|
||||
|
||||
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
|
||||
|
||||
try:
|
||||
execfile=execfile #Not in Py3k
|
||||
except NameError:
|
||||
from _pydev_execfile import execfile
|
||||
from _pydev_imps._pydev_execfile import execfile
|
||||
|
||||
|
||||
try:
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_Queue as _queue
|
||||
from _pydev_imps import _pydev_Queue as _queue
|
||||
else:
|
||||
import Queue as _queue
|
||||
except:
|
||||
import queue as _queue #@UnresolvedImport
|
||||
|
||||
|
||||
try:
|
||||
from pydevd_exec import Exec
|
||||
except:
|
||||
from pydevd_exec2 import Exec
|
||||
|
||||
try:
|
||||
from urllib import quote
|
||||
from urllib import quote, quote_plus, unquote_plus
|
||||
except:
|
||||
from urllib.parse import quote #@UnresolvedImport
|
||||
from urllib.parse import quote, quote_plus, unquote_plus #@UnresolvedImport
|
||||
|
||||
|
||||
import os
|
||||
@@ -80,7 +92,7 @@ except:
|
||||
return start
|
||||
|
||||
i = 0
|
||||
for start_seg, dest_seg in zip(orig_list, dest_list):
|
||||
for start_seg, dest_seg in izip(orig_list, dest_list):
|
||||
if start_seg != os.path.normcase(dest_seg):
|
||||
break
|
||||
i += 1
|
||||
|
||||
@@ -31,7 +31,7 @@ GLUT Inputhook support functions
|
||||
#-----------------------------------------------------------------------------
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from _pydev_imps import _pydev_time as time
|
||||
import signal
|
||||
import OpenGL.GLUT as glut
|
||||
import OpenGL.platform as platform
|
||||
|
||||
@@ -22,7 +22,7 @@ Authors
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from _pydev_imps import _pydev_time as time
|
||||
from timeit import default_timer as clock
|
||||
import pyglet
|
||||
from pydev_ipython.inputhook import stdin_ready
|
||||
|
||||
@@ -19,11 +19,7 @@ Author: Christian Boos
|
||||
import os
|
||||
import signal
|
||||
|
||||
from pydevd_constants import USE_LIB_COPY
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
import threading
|
||||
|
||||
|
||||
from pydev_ipython.qt_for_kernel import QtCore, QtGui
|
||||
|
||||
@@ -19,7 +19,7 @@ Authors: Robin Dunn, Brian Granger, Ondrej Certik
|
||||
|
||||
import sys
|
||||
import signal
|
||||
import time
|
||||
from _pydev_imps import _pydev_time as time
|
||||
from timeit import default_timer as clock
|
||||
import wx
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import sys
|
||||
from pydev_console_utils import BaseInterpreterInterface
|
||||
import re
|
||||
|
||||
import os
|
||||
|
||||
@@ -10,7 +9,7 @@ os.environ['TERM'] = 'emacs' #to use proper page_more() for paging
|
||||
# Uncomment to force PyDev standard shell.
|
||||
# raise ImportError()
|
||||
|
||||
from pydev_ipython_console_011 import PyDevFrontEnd
|
||||
from pydev_ipython_console_011 import get_pydev_frontend
|
||||
|
||||
#=======================================================================================================================
|
||||
# InterpreterInterface
|
||||
@@ -24,7 +23,7 @@ class InterpreterInterface(BaseInterpreterInterface):
|
||||
BaseInterpreterInterface.__init__(self, mainThread)
|
||||
self.client_port = client_port
|
||||
self.host = host
|
||||
self.interpreter = PyDevFrontEnd(host, client_port)
|
||||
self.interpreter = get_pydev_frontend(host, client_port)
|
||||
self._input_error_printed = False
|
||||
self.notification_succeeded = False
|
||||
self.notification_tries = 0
|
||||
|
||||
@@ -19,7 +19,6 @@ import os
|
||||
import codeop
|
||||
|
||||
from IPython.core.error import UsageError
|
||||
from IPython.core.inputsplitter import IPythonInputSplitter
|
||||
from IPython.core.completer import IPCompleter
|
||||
from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
|
||||
from IPython.core.usage import default_banner_parts
|
||||
@@ -53,7 +52,8 @@ def show_in_pager(self, strng):
|
||||
print(strng)
|
||||
|
||||
def create_editor_hook(pydev_host, pydev_client_port):
|
||||
def call_editor(self, filename, line=0, wait=True):
|
||||
|
||||
def call_editor(filename, line=0, wait=True):
|
||||
""" Open an editor in PyDev """
|
||||
if line is None:
|
||||
line = 0
|
||||
@@ -62,6 +62,9 @@ def create_editor_hook(pydev_host, pydev_client_port):
|
||||
# we don't launch a process. This is more like what happens in the zmqshell
|
||||
filename = os.path.abspath(filename)
|
||||
|
||||
# import sys
|
||||
# sys.__stderr__.write('Calling editor at: %s:%s\n' % (pydev_host, pydev_client_port))
|
||||
|
||||
# Tell PyDev to open the editor
|
||||
server = xmlrpclib.Server('http://%s:%s' % (pydev_host, pydev_client_port))
|
||||
server.IPythonEditor(filename, str(line))
|
||||
@@ -291,22 +294,17 @@ class PyDevTerminalInteractiveShell(TerminalInteractiveShell):
|
||||
InteractiveShellABC.register(PyDevTerminalInteractiveShell) # @UndefinedVariable
|
||||
|
||||
#=======================================================================================================================
|
||||
# PyDevFrontEnd
|
||||
# _PyDevFrontEnd
|
||||
#=======================================================================================================================
|
||||
class PyDevFrontEnd:
|
||||
class _PyDevFrontEnd:
|
||||
|
||||
version = release.__version__
|
||||
|
||||
def __init__(self, pydev_host, pydev_client_port, *args, **kwarg):
|
||||
def __init__(self, *args, **kwarg):
|
||||
|
||||
# Create and initialize our IPython instance.
|
||||
self.ipython = PyDevTerminalInteractiveShell.instance()
|
||||
|
||||
# Back channel to PyDev to open editors (in the future other
|
||||
# info may go back this way. This is the same channel that is
|
||||
# used to get stdin, see StdIn in pydev_console_utils)
|
||||
self.ipython.set_hook('editor', create_editor_hook(pydev_host, pydev_client_port))
|
||||
|
||||
# Display the IPython banner, this has version info and
|
||||
# help info
|
||||
self.ipython.show_banner()
|
||||
@@ -412,6 +410,9 @@ class PyDevFrontEnd:
|
||||
|
||||
def getNamespace(self):
|
||||
return self.ipython.user_ns
|
||||
|
||||
def clearBuffer(self):
|
||||
del self._curr_exec_lines[:]
|
||||
|
||||
def addExec(self, line):
|
||||
if self._curr_exec_lines:
|
||||
@@ -463,3 +464,28 @@ IPython.lib.inputhook.enable_gui = pydev_ipython.inputhook.enable_gui
|
||||
# rely on using the inputhooks directly.
|
||||
for name in pydev_ipython.inputhook.__all__:
|
||||
setattr(IPython.lib.inputhook, name, getattr(pydev_ipython.inputhook, name))
|
||||
|
||||
|
||||
class _PyDevFrontEndContainer:
|
||||
_instance = None
|
||||
_last_host_port = None
|
||||
|
||||
def get_pydev_frontend(pydev_host, pydev_client_port):
|
||||
if _PyDevFrontEndContainer._instance is None:
|
||||
_PyDevFrontEndContainer._instance = _PyDevFrontEnd()
|
||||
|
||||
if _PyDevFrontEndContainer._last_host_port != (pydev_host, pydev_client_port):
|
||||
_PyDevFrontEndContainer._last_host_port = pydev_host, pydev_client_port
|
||||
|
||||
# Back channel to PyDev to open editors (in the future other
|
||||
# info may go back this way. This is the same channel that is
|
||||
# used to get stdin, see StdIn in pydev_console_utils)
|
||||
_PyDevFrontEndContainer._instance.ipython.hooks['editor'] = create_editor_hook(pydev_host, pydev_client_port)
|
||||
|
||||
# Note: setting the callback directly because setting it with set_hook would actually create a chain instead
|
||||
# of ovewriting at each new call).
|
||||
# _PyDevFrontEndContainer._instance.ipython.set_hook('editor', create_editor_hook(pydev_host, pydev_client_port))
|
||||
|
||||
return _PyDevFrontEndContainer._instance
|
||||
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import pydevd_constants
|
||||
if pydevd_constants.USE_LIB_COPY:
|
||||
import _pydev_socket as socket
|
||||
else:
|
||||
import socket
|
||||
from _pydev_imps import _pydev_socket as socket
|
||||
|
||||
_cache = None
|
||||
def get_localhost():
|
||||
'''
|
||||
Should return 127.0.0.1 in ipv4 and ::1 in ipv6
|
||||
|
||||
|
||||
localhost is not used because on windows vista/windows 7, there can be issues where the resolving doesn't work
|
||||
properly and takes a lot of time (had this issue on the pyunit server).
|
||||
|
||||
properly and takes a lot of time (had this issue on the pyunit server).
|
||||
|
||||
Using the IP directly solves the problem.
|
||||
'''
|
||||
#TODO: Needs better investigation!
|
||||
|
||||
|
||||
global _cache
|
||||
if _cache is None:
|
||||
try:
|
||||
|
||||
@@ -5,6 +5,8 @@ import traceback
|
||||
|
||||
pydev_src_dir = os.path.dirname(__file__)
|
||||
|
||||
from pydevd_constants import xrange
|
||||
|
||||
def is_python(path):
|
||||
if path.endswith("'") or path.endswith('"'):
|
||||
path = path[1:len(path)-1]
|
||||
@@ -102,7 +104,7 @@ def str_to_args_windows(args):
|
||||
buf = ''
|
||||
|
||||
args_len = len(args)
|
||||
for i in range(args_len):
|
||||
for i in xrange(args_len):
|
||||
ch = args[i]
|
||||
if (ch == '\\'):
|
||||
backslashes+=1
|
||||
@@ -385,3 +387,118 @@ def patch_new_process_functions_with_warning():
|
||||
except ImportError:
|
||||
import _winapi as _subprocess
|
||||
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcessWarnMultiproc)
|
||||
|
||||
|
||||
|
||||
class _NewThreadStartupWithTrace:
|
||||
|
||||
def __init__(self, original_func, args, kwargs):
|
||||
self.original_func = original_func
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __call__(self):
|
||||
from pydevd_comm import GetGlobalDebugger
|
||||
global_debugger = GetGlobalDebugger()
|
||||
if global_debugger is not None:
|
||||
global_debugger.SetTrace(global_debugger.trace_dispatch)
|
||||
|
||||
return self.original_func(*self.args, **self.kwargs)
|
||||
|
||||
class _NewThreadStartupWithoutTrace:
|
||||
|
||||
def __init__(self, original_func, args, kwargs):
|
||||
self.original_func = original_func
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __call__(self):
|
||||
return self.original_func(*self.args, **self.kwargs)
|
||||
|
||||
_UseNewThreadStartup = _NewThreadStartupWithTrace
|
||||
|
||||
def _get_threading_modules_to_patch():
|
||||
threading_modules_to_patch = []
|
||||
try:
|
||||
import thread as _thread
|
||||
threading_modules_to_patch.append(_thread)
|
||||
except:
|
||||
import _thread
|
||||
threading_modules_to_patch.append(_thread)
|
||||
return 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:
|
||||
_original_start_new_thread = thread._original_start_new_thread = thread.start_new_thread
|
||||
else:
|
||||
_original_start_new_thread = thread._original_start_new_thread
|
||||
|
||||
|
||||
class ClassWithPydevStartNewThread:
|
||||
|
||||
def pydev_start_new_thread(self, function, args=(), kwargs={}):
|
||||
'''
|
||||
We need to replace the original thread.start_new_thread with this function so that threads started
|
||||
through it and not through the threading module are properly traced.
|
||||
'''
|
||||
return _original_start_new_thread(_UseNewThreadStartup(function, args, kwargs), ())
|
||||
|
||||
# This is a hack for the situation where the thread.start_new_thread is declared inside a class, such as the one below
|
||||
# class F(object):
|
||||
# start_new_thread = thread.start_new_thread
|
||||
#
|
||||
# def start_it(self):
|
||||
# self.start_new_thread(self.function, args, kwargs)
|
||||
# So, if it's an already bound method, calling self.start_new_thread won't really receive a different 'self' -- it
|
||||
# does work in the default case because in builtins self isn't passed either.
|
||||
pydev_start_new_thread = ClassWithPydevStartNewThread().pydev_start_new_thread
|
||||
|
||||
try:
|
||||
# We need to replace the original thread.start_new_thread with this function so that threads started through
|
||||
# it and not through the threading module are properly traced.
|
||||
thread.start_new_thread = pydev_start_new_thread
|
||||
thread.start_new = pydev_start_new_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:
|
||||
t.start_new_thread = t._original_start_new_thread
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
t.start_new = t._original_start_new_thread
|
||||
except:
|
||||
pass
|
||||
|
||||
def disable_trace_thread_modules():
|
||||
'''
|
||||
Can be used to temporarily stop tracing threads created with thread.start_new_thread.
|
||||
'''
|
||||
global _UseNewThreadStartup
|
||||
_UseNewThreadStartup = _NewThreadStartupWithoutTrace
|
||||
|
||||
|
||||
def enable_trace_thread_modules():
|
||||
'''
|
||||
Can be used to start tracing threads created with thread.start_new_thread again.
|
||||
'''
|
||||
global _UseNewThreadStartup
|
||||
_UseNewThreadStartup = _NewThreadStartupWithTrace
|
||||
|
||||
def get_original_start_new_thread(threading_module):
|
||||
try:
|
||||
return threading_module._original_start_new_thread
|
||||
except:
|
||||
return threading_module.start_new_thread
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import unittest
|
||||
from _pydev_imps import _pydev_thread
|
||||
try:
|
||||
import Queue
|
||||
except:
|
||||
@@ -282,13 +283,9 @@ class ClientThread(threading.Thread):
|
||||
if False:
|
||||
proc = subprocess.Popen(args, env=os.environ, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
stdout_thread = threading.Thread(target=self._reader_thread,args=(proc.stdout, sys.stdout))
|
||||
stdout_thread.setDaemon(True)
|
||||
stdout_thread.start()
|
||||
_pydev_thread.start_new_thread(self._reader_thread,(proc.stdout, sys.stdout))
|
||||
|
||||
stderr_thread = threading.Thread(target=self._reader_thread,args=(proc.stderr, sys.stderr))
|
||||
stderr_thread.setDaemon(True)
|
||||
stderr_thread.start()
|
||||
_pydev_thread.start_new_thread(target=self._reader_thread,args=(proc.stderr, sys.stderr))
|
||||
else:
|
||||
proc = subprocess.Popen(args, env=os.environ, shell=False)
|
||||
proc.wait()
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
from pydevd_constants import * #@UnusedWildImport
|
||||
try:
|
||||
from Queue import Queue
|
||||
except:
|
||||
from queue import Queue #@UnresolvedImport
|
||||
import threading
|
||||
from pydev_imports import xmlrpclib
|
||||
from pydev_imports import xmlrpclib, _queue
|
||||
Queue = _queue.Queue
|
||||
import traceback
|
||||
import time
|
||||
from pydev_runfiles_coverage import StartCoverageSupportFromParams
|
||||
|
||||
|
||||
@@ -15,7 +10,7 @@ from pydev_runfiles_coverage import StartCoverageSupportFromParams
|
||||
# ParallelNotification
|
||||
#=======================================================================================================================
|
||||
class ParallelNotification(object):
|
||||
|
||||
|
||||
def __init__(self, method, args, kwargs):
|
||||
self.method = method
|
||||
self.args = args
|
||||
@@ -23,8 +18,8 @@ class ParallelNotification(object):
|
||||
|
||||
def ToTuple(self):
|
||||
return self.method, self.args, self.kwargs
|
||||
|
||||
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# KillServer
|
||||
#=======================================================================================================================
|
||||
@@ -37,9 +32,9 @@ class KillServer(object):
|
||||
# ServerComm
|
||||
#=======================================================================================================================
|
||||
class ServerComm(threading.Thread):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def __init__(self, job_id, server):
|
||||
self.notifications_queue = Queue()
|
||||
threading.Thread.__init__(self)
|
||||
@@ -47,11 +42,11 @@ class ServerComm(threading.Thread):
|
||||
assert job_id is not None
|
||||
assert port is not None
|
||||
self.job_id = job_id
|
||||
|
||||
|
||||
self.finished = False
|
||||
self.server = server
|
||||
|
||||
|
||||
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
kill_found = False
|
||||
@@ -62,7 +57,7 @@ class ServerComm(threading.Thread):
|
||||
else:
|
||||
assert isinstance(command, ParallelNotification)
|
||||
commands.append(command.ToTuple())
|
||||
|
||||
|
||||
try:
|
||||
while True:
|
||||
command = self.notifications_queue.get(block=False) #No block to create a batch.
|
||||
@@ -85,7 +80,7 @@ class ServerComm(threading.Thread):
|
||||
self.server.lock.release()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
if kill_found:
|
||||
self.finished = True
|
||||
return
|
||||
@@ -96,27 +91,27 @@ class ServerComm(threading.Thread):
|
||||
# ServerFacade
|
||||
#=======================================================================================================================
|
||||
class ServerFacade(object):
|
||||
|
||||
|
||||
|
||||
|
||||
def __init__(self, notifications_queue):
|
||||
self.notifications_queue = notifications_queue
|
||||
|
||||
|
||||
|
||||
|
||||
def notifyTestsCollected(self, *args, **kwargs):
|
||||
pass #This notification won't be passed
|
||||
|
||||
|
||||
|
||||
|
||||
def notifyTestRunFinished(self, *args, **kwargs):
|
||||
pass #This notification won't be passed
|
||||
|
||||
|
||||
|
||||
|
||||
def notifyStartTest(self, *args, **kwargs):
|
||||
self.notifications_queue.put_nowait(ParallelNotification('notifyStartTest', args, kwargs))
|
||||
|
||||
|
||||
|
||||
|
||||
def notifyTest(self, *args, **kwargs):
|
||||
self.notifications_queue.put_nowait(ParallelNotification('notifyTest', args, kwargs))
|
||||
|
||||
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
@@ -124,25 +119,25 @@ class ServerFacade(object):
|
||||
#=======================================================================================================================
|
||||
def run_client(job_id, port, verbosity, coverage_output_file, coverage_include):
|
||||
job_id = int(job_id)
|
||||
|
||||
|
||||
import pydev_localhost
|
||||
server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), port))
|
||||
server.lock = threading.Lock()
|
||||
|
||||
|
||||
|
||||
server_comm = ServerComm(job_id, server)
|
||||
server_comm.start()
|
||||
|
||||
|
||||
try:
|
||||
server_facade = ServerFacade(server_comm.notifications_queue)
|
||||
import pydev_runfiles
|
||||
import pydev_runfiles_xml_rpc
|
||||
pydev_runfiles_xml_rpc.SetServer(server_facade)
|
||||
|
||||
|
||||
#Starts None and when the 1st test is gotten, it's started (because a server may be initiated and terminated
|
||||
#before receiving any test -- which would mean a different process got all the tests to run).
|
||||
coverage = None
|
||||
|
||||
|
||||
try:
|
||||
tests_to_run = [1]
|
||||
while tests_to_run:
|
||||
@@ -153,34 +148,34 @@ def run_client(job_id, port, verbosity, coverage_output_file, coverage_include):
|
||||
tests_to_run = server.GetTestsToRun(job_id)
|
||||
finally:
|
||||
server.lock.release()
|
||||
|
||||
|
||||
if not tests_to_run:
|
||||
break
|
||||
|
||||
|
||||
if coverage is None:
|
||||
_coverage_files, coverage = StartCoverageSupportFromParams(
|
||||
None, coverage_output_file, 1, coverage_include)
|
||||
|
||||
|
||||
|
||||
files_to_tests = {}
|
||||
for test in tests_to_run:
|
||||
filename_and_test = test.split('|')
|
||||
if len(filename_and_test) == 2:
|
||||
files_to_tests.setdefault(filename_and_test[0], []).append(filename_and_test[1])
|
||||
|
||||
|
||||
configuration = pydev_runfiles.Configuration(
|
||||
'',
|
||||
verbosity,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
files_to_tests,
|
||||
'',
|
||||
verbosity,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
files_to_tests,
|
||||
1, #Always single job here
|
||||
None,
|
||||
|
||||
None,
|
||||
|
||||
#The coverage is handled in this loop.
|
||||
coverage_output_file=None,
|
||||
coverage_include=None,
|
||||
coverage_output_file=None,
|
||||
coverage_include=None,
|
||||
)
|
||||
test_runner = pydev_runfiles.PydevTestRunner(configuration)
|
||||
sys.stdout.flush()
|
||||
@@ -190,11 +185,11 @@ def run_client(job_id, port, verbosity, coverage_output_file, coverage_include):
|
||||
coverage.stop()
|
||||
coverage.save()
|
||||
|
||||
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
server_comm.notifications_queue.put_nowait(KillServer())
|
||||
|
||||
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
@@ -204,16 +199,16 @@ if __name__ == '__main__':
|
||||
if len(sys.argv) -1 == 3:
|
||||
job_id, port, verbosity = sys.argv[1:]
|
||||
coverage_output_file, coverage_include = None, None
|
||||
|
||||
|
||||
elif len(sys.argv) -1 == 5:
|
||||
job_id, port, verbosity, coverage_output_file, coverage_include = sys.argv[1:]
|
||||
|
||||
|
||||
else:
|
||||
raise AssertionError('Could not find out how to handle the parameters: '+sys.argv[1:])
|
||||
|
||||
|
||||
job_id = int(job_id)
|
||||
port = int(port)
|
||||
verbosity = int(verbosity)
|
||||
run_client(job_id, port, verbosity, coverage_output_file, coverage_include)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,15 +3,10 @@ import traceback
|
||||
import warnings
|
||||
|
||||
from _pydev_filesystem_encoding import getfilesystemencoding
|
||||
from pydev_imports import xmlrpclib
|
||||
from pydev_imports import xmlrpclib, _queue
|
||||
Queue = _queue.Queue
|
||||
from pydevd_constants import *
|
||||
|
||||
|
||||
try:
|
||||
from Queue import Queue
|
||||
except:
|
||||
from queue import Queue
|
||||
|
||||
#This may happen in IronPython (in Python it shouldn't happen as there are
|
||||
#'fast' replacements that are used in xmlrpclib.py)
|
||||
warnings.filterwarnings(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from _pydev_imps._pydev_thread import start_new_thread
|
||||
|
||||
try:
|
||||
from code import InteractiveConsole
|
||||
except ImportError:
|
||||
@@ -9,13 +11,7 @@ from code import InteractiveInterpreter
|
||||
import os
|
||||
import sys
|
||||
|
||||
from pydevd_constants import USE_LIB_COPY
|
||||
from pydevd_constants import IS_JYTHON
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
import _pydev_threading as threading
|
||||
|
||||
import traceback
|
||||
import fix_getpass
|
||||
@@ -23,15 +19,7 @@ fix_getpass.fixGetpass()
|
||||
|
||||
import pydevd_vars
|
||||
|
||||
from pydev_imports import Exec
|
||||
|
||||
try:
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_Queue as _queue
|
||||
else:
|
||||
import Queue as _queue
|
||||
except:
|
||||
import queue as _queue
|
||||
from pydev_imports import Exec, _queue
|
||||
|
||||
try:
|
||||
import __builtin__
|
||||
@@ -59,17 +47,6 @@ except:
|
||||
#That's OK, not all versions of python have sys.version_info
|
||||
pass
|
||||
|
||||
try:
|
||||
try:
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_xmlrpclib as xmlrpclib
|
||||
else:
|
||||
import xmlrpclib
|
||||
except ImportError:
|
||||
import xmlrpc.client as xmlrpclib
|
||||
except ImportError:
|
||||
import _pydev_xmlrpclib as xmlrpclib
|
||||
|
||||
|
||||
class Command:
|
||||
def __init__(self, interpreter, code_fragment):
|
||||
@@ -81,13 +58,14 @@ class Command:
|
||||
self.code_fragment = code_fragment
|
||||
self.more = None
|
||||
|
||||
@staticmethod
|
||||
|
||||
def symbol_for_fragment(code_fragment):
|
||||
if code_fragment.is_single_line:
|
||||
symbol = 'single'
|
||||
else:
|
||||
symbol = 'exec' # Jython doesn't support this
|
||||
return symbol
|
||||
symbol_for_fragment = staticmethod(symbol_for_fragment)
|
||||
|
||||
def run(self):
|
||||
text = self.code_fragment.text
|
||||
@@ -248,7 +226,7 @@ except:
|
||||
#=======================================================================================================================
|
||||
# _DoExit
|
||||
#=======================================================================================================================
|
||||
def DoExit(*args):
|
||||
def _DoExit(*args):
|
||||
'''
|
||||
We have to override the exit because calling sys.exit will only actually exit the main thread,
|
||||
and as we're in a Xml-rpc server, that won't work.
|
||||
@@ -312,7 +290,6 @@ def start_server(host, port, interpreter):
|
||||
sys.stderr.write(interpreter.get_greeting_msg())
|
||||
sys.stderr.flush()
|
||||
|
||||
interpreter.server = server
|
||||
server.serve_forever()
|
||||
|
||||
return server
|
||||
@@ -321,15 +298,11 @@ def start_server(host, port, interpreter):
|
||||
def StartServer(host, port, client_port):
|
||||
#replace exit (see comments on method)
|
||||
#note that this does not work in jython!!! (sys method can't be replaced).
|
||||
sys.exit = DoExit
|
||||
sys.exit = _DoExit
|
||||
|
||||
interpreter = InterpreterInterface(host, client_port, threading.currentThread())
|
||||
|
||||
server_thread = threading.Thread(target=start_server,
|
||||
name='ServerThread',
|
||||
args=(host, port, interpreter))
|
||||
server_thread.setDaemon(True)
|
||||
server_thread.start()
|
||||
start_new_thread(start_server,(host, port, interpreter))
|
||||
|
||||
process_exec_queue(interpreter)
|
||||
|
||||
|
||||
+173
-242
@@ -2,10 +2,12 @@
|
||||
from __future__ import nested_scopes # Jython 2.1 support
|
||||
from pydevd_constants import * # @UnusedWildImport
|
||||
|
||||
import pydev_monkey_qt
|
||||
pydev_monkey_qt.patch_qt()
|
||||
|
||||
import traceback
|
||||
|
||||
from django_debug import DjangoLineBreakpoint
|
||||
from pydevd_signature import SignatureFactory
|
||||
from pydevd_frame import add_exception_to_frame
|
||||
import pydev_imports
|
||||
from pydevd_breakpoints import * #@UnusedWildImport
|
||||
@@ -69,7 +71,9 @@ from pydevd_comm import CMD_CHANGE_VARIABLE, \
|
||||
CMD_ENABLE_DONT_TRACE, \
|
||||
CMD_GET_FILE_CONTENTS,\
|
||||
CMD_SET_PROPERTY_TRACE, CMD_RUN_CUSTOM_OPERATION,\
|
||||
InternalRunCustomOperation
|
||||
InternalRunCustomOperation, CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression,\
|
||||
InternalConsoleGetCompletions
|
||||
|
||||
from pydevd_file_utils import NormFileToServer, GetFilenameAndBase
|
||||
import pydevd_file_utils
|
||||
import pydevd_vars
|
||||
@@ -77,19 +81,16 @@ import pydevd_vm_type
|
||||
import pydevd_tracing
|
||||
import pydevd_io
|
||||
from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
|
||||
from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit, addCustomFrame
|
||||
from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit
|
||||
import pydevd_dont_trace
|
||||
import pydevd_traceproperty
|
||||
|
||||
from _pydev_imps import _pydev_time as time, _pydev_thread
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_time as time
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import time
|
||||
import threading
|
||||
import _pydev_threading as threading
|
||||
|
||||
import os
|
||||
import atexit
|
||||
|
||||
|
||||
threadingEnumerate = threading.enumerate
|
||||
@@ -102,7 +103,6 @@ except:
|
||||
|
||||
DONT_TRACE = {
|
||||
# commonly used things from the stdlib that we don't want to trace
|
||||
'threading.py':1,
|
||||
'Queue.py':1,
|
||||
'queue.py':1,
|
||||
'socket.py':1,
|
||||
@@ -111,12 +111,21 @@ DONT_TRACE = {
|
||||
'threading.py':1,
|
||||
|
||||
#things from pydev that we don't want to trace
|
||||
'_pydev_execfile.py':1,
|
||||
'_pydev_jython_execfile.py':1,
|
||||
'_pydev_threading':1,
|
||||
'_pydev_Queue':1,
|
||||
'django_debug.py':1,
|
||||
'django_frame.py':1,
|
||||
'pydev_log.py':1,
|
||||
'pydev_monkey.py':1 ,
|
||||
'pydevd.py':1 ,
|
||||
'pydevd_additional_thread_info.py':1,
|
||||
'pydevd_custom_frames.py':1,
|
||||
'pydevd_comm.py':1,
|
||||
'pydevd_console.py':1 ,
|
||||
'pydevd_constants.py':1,
|
||||
'pydevd_custom_frames.py':1,
|
||||
'pydevd_dont_trace.py':1,
|
||||
'pydevd_exec.py':1,
|
||||
'pydevd_exec2.py':1,
|
||||
'pydevd_file_utils.py':1,
|
||||
@@ -124,18 +133,18 @@ DONT_TRACE = {
|
||||
'pydevd_import_class.py':1 ,
|
||||
'pydevd_io.py':1 ,
|
||||
'pydevd_psyco_stub.py':1,
|
||||
'pydevd_referrers.py':1 ,
|
||||
'pydevd_reload.py':1 ,
|
||||
'pydevd_resolver.py':1 ,
|
||||
'pydevd_save_locals.py':1 ,
|
||||
'pydevd_signature.py':1,
|
||||
'pydevd_stackless.py':1 ,
|
||||
'pydevd_traceproperty.py':1,
|
||||
'pydevd_tracing.py':1 ,
|
||||
'pydevd_signature.py':1,
|
||||
'pydevd_utils.py':1,
|
||||
'pydevd_vars.py':1,
|
||||
'pydevd_vm_type.py':1,
|
||||
'_pydev_execfile.py':1,
|
||||
'_pydev_jython_execfile.py':1,
|
||||
'pydevd_dont_trace.py':1,
|
||||
'pydevd_xml.py':1,
|
||||
}
|
||||
|
||||
if IS_PY3K:
|
||||
@@ -155,17 +164,28 @@ remote = False
|
||||
from _pydev_filesystem_encoding import getfilesystemencoding
|
||||
file_system_encoding = getfilesystemencoding()
|
||||
|
||||
def isThreadAlive(t):
|
||||
try:
|
||||
# If thread is not started yet we treat it as alive.
|
||||
# It is required to debug threads started by start_new_thread in Python 3.4
|
||||
if hasattr(t, '_is_stopped'):
|
||||
alive = not t._is_stopped
|
||||
else:
|
||||
alive = not t.__stopped
|
||||
except:
|
||||
alive = t.isAlive()
|
||||
return alive
|
||||
|
||||
# Hack for https://sw-brainwy.rhcloud.com/tracker/PyDev/363 (i.e.: calling isAlive() can throw AssertionError under some circumstances)
|
||||
# It is required to debug threads started by start_new_thread in Python 3.4
|
||||
_temp = threading.Thread()
|
||||
if hasattr(_temp, '_is_stopped'): # Python 3.4 has this
|
||||
def isThreadAlive(t):
|
||||
try:
|
||||
return not t._is_stopped
|
||||
except:
|
||||
return t.isAlive()
|
||||
|
||||
elif hasattr(_temp, '_Thread__stopped'): # Python 2.7 has this
|
||||
def isThreadAlive(t):
|
||||
try:
|
||||
return not t._Thread__stopped
|
||||
except:
|
||||
return t.isAlive()
|
||||
|
||||
else: # Haven't checked all other versions, so, let's use the regular isAlive call in this case.
|
||||
def isThreadAlive(t):
|
||||
return t.isAlive()
|
||||
del _temp
|
||||
|
||||
#=======================================================================================================================
|
||||
# PyDBCommandThread
|
||||
@@ -179,7 +199,7 @@ class PyDBCommandThread(PyDBDaemonThread):
|
||||
self.setName('pydevd.CommandThread')
|
||||
|
||||
def OnRun(self):
|
||||
for i in range(1, 10):
|
||||
for i in xrange(1, 10):
|
||||
time.sleep(0.5) #this one will only start later on (because otherwise we may not have any non-daemon threads
|
||||
if self.killReceived:
|
||||
return
|
||||
@@ -203,7 +223,7 @@ class PyDBCommandThread(PyDBDaemonThread):
|
||||
|
||||
|
||||
def killAllPydevThreads():
|
||||
threads = threadingEnumerate()
|
||||
threads = DictKeys(PyDBDaemonThread.created_pydb_daemon_threads)
|
||||
for t in threads:
|
||||
if hasattr(t, 'doKillPydevThread'):
|
||||
t.doKillPydevThread()
|
||||
@@ -217,12 +237,23 @@ class PyDBCheckAliveThread(PyDBDaemonThread):
|
||||
def __init__(self, pyDb):
|
||||
PyDBDaemonThread.__init__(self)
|
||||
self.pyDb = pyDb
|
||||
self.setDaemon(False)
|
||||
self.setName('pydevd.CheckAliveThread')
|
||||
|
||||
def OnRun(self):
|
||||
if self.dontTraceMe:
|
||||
self.pyDb.SetTrace(None) # no debugging on this thread
|
||||
|
||||
disable_tracing = True
|
||||
|
||||
if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON and sys.hexversion <= 0x020201f0:
|
||||
# don't run untraced threads if we're in jython 2.2.1 or lower
|
||||
# jython bug: if we start a thread and another thread changes the tracing facility
|
||||
# it affects other threads (it's not set only for the thread but globally)
|
||||
# Bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1870039&group_id=12867&atid=112867
|
||||
disable_tracing = False
|
||||
|
||||
if disable_tracing:
|
||||
pydevd_tracing.SetTrace(None) # no debugging on this thread
|
||||
|
||||
while not self.killReceived:
|
||||
if not self.pyDb.haveAliveThreads():
|
||||
try:
|
||||
@@ -240,63 +271,6 @@ class PyDBCheckAliveThread(PyDBDaemonThread):
|
||||
def doKillPydevThread(self):
|
||||
pass
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_thread as thread
|
||||
else:
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
import _thread as thread #Py3K changed it.
|
||||
|
||||
_original_start_new_thread = thread.start_new_thread
|
||||
|
||||
if getattr(thread, '_original_start_new_thread', None) is None:
|
||||
thread._original_start_new_thread = thread.start_new_thread
|
||||
|
||||
#=======================================================================================================================
|
||||
# NewThreadStartup
|
||||
#=======================================================================================================================
|
||||
class NewThreadStartup:
|
||||
|
||||
def __init__(self, original_func, args, kwargs):
|
||||
self.original_func = original_func
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __call__(self):
|
||||
global_debugger = GetGlobalDebugger()
|
||||
if global_debugger is not None:
|
||||
global_debugger.SetTrace(global_debugger.trace_dispatch)
|
||||
return self.original_func(*self.args, **self.kwargs)
|
||||
|
||||
thread.NewThreadStartup = NewThreadStartup
|
||||
|
||||
#=======================================================================================================================
|
||||
# pydev_start_new_thread
|
||||
#=======================================================================================================================
|
||||
def _pydev_start_new_thread(function, args, kwargs={}):
|
||||
'''
|
||||
We need to replace the original thread.start_new_thread with this function so that threads started through
|
||||
it and not through the threading module are properly traced.
|
||||
'''
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_thread as thread
|
||||
else:
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
import _thread as thread #Py3K changed it.
|
||||
|
||||
return thread._original_start_new_thread(thread.NewThreadStartup(function, args, kwargs), ())
|
||||
|
||||
class PydevStartNewThread(object):
|
||||
def __get__(self, obj, type=None):
|
||||
return self
|
||||
|
||||
def __call__(self, function, args, kwargs={}):
|
||||
return _pydev_start_new_thread(function, args, kwargs)
|
||||
|
||||
pydev_start_new_thread = PydevStartNewThread()
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
@@ -332,12 +306,15 @@ class PyDB:
|
||||
self.file_to_id_to_line_breakpoint = {}
|
||||
self.file_to_id_to_django_breakpoint = {}
|
||||
|
||||
# Note: breakpoints dict should not be mutated: a copy should be created
|
||||
# and later it should be assigned back (to prevent concurrency issues).
|
||||
self.break_on_uncaught_exceptions = {}
|
||||
self.break_on_caught_exceptions = {}
|
||||
|
||||
self.django_exception_break = {}
|
||||
self.readyToRun = False
|
||||
self._main_lock = threading.Lock()
|
||||
self._lock_running_thread_ids = threading.Lock()
|
||||
self._main_lock = _pydev_thread.allocate_lock()
|
||||
self._lock_running_thread_ids = _pydev_thread.allocate_lock()
|
||||
self._py_db_command_thread_event = threading.Event()
|
||||
CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event
|
||||
self._finishDebuggingSession = False
|
||||
@@ -370,7 +347,11 @@ class PyDB:
|
||||
|
||||
def haveAliveThreads(self):
|
||||
for t in threadingEnumerate():
|
||||
if not isinstance(t, PyDBDaemonThread) and isThreadAlive(t) and not t.isDaemon():
|
||||
if isinstance(t, PyDBDaemonThread):
|
||||
pydev_log.error_once(
|
||||
'Error in debugger: Found PyDBDaemonThread through threading.enumerate().\n')
|
||||
|
||||
if isThreadAlive(t) and not t.isDaemon():
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -425,11 +406,9 @@ class PyDB:
|
||||
if thread_id == "*":
|
||||
threads = threadingEnumerate()
|
||||
for t in threads:
|
||||
thread_name = t.getName()
|
||||
if not thread_name.startswith('pydevd.') or thread_name == 'pydevd.CommandThread':
|
||||
thread_id = GetThreadId(t)
|
||||
queue = self.getInternalQueue(thread_id)
|
||||
queue.put(int_cmd)
|
||||
thread_id = GetThreadId(t)
|
||||
queue = self.getInternalQueue(thread_id)
|
||||
queue.put(int_cmd)
|
||||
|
||||
else:
|
||||
queue = self.getInternalQueue(thread_id)
|
||||
@@ -480,7 +459,13 @@ class PyDB:
|
||||
for t in all_threads:
|
||||
thread_id = GetThreadId(t)
|
||||
|
||||
if not isinstance(t, PyDBDaemonThread) and isThreadAlive(t):
|
||||
if isinstance(t, PyDBDaemonThread):
|
||||
pydev_log.error_once('Found PyDBDaemonThread in threading.enumerate.')
|
||||
|
||||
elif getattr(t, 'is_pydev_daemon_thread', False):
|
||||
pass # I.e.: skip the DummyThreads created from pydev daemon threads
|
||||
|
||||
elif isThreadAlive(t):
|
||||
program_threads_alive[thread_id] = t
|
||||
|
||||
if not DictContains(self._running_thread_ids, thread_id):
|
||||
@@ -543,19 +528,18 @@ class PyDB:
|
||||
threads = threadingEnumerate()
|
||||
try:
|
||||
for t in threads:
|
||||
if not t.getName().startswith('pydevd.'):
|
||||
# TODO: optimize so that we only actually add that tracing if it's in
|
||||
# the new breakpoint context.
|
||||
additionalInfo = None
|
||||
try:
|
||||
additionalInfo = t.additionalInfo
|
||||
except AttributeError:
|
||||
pass # that's ok, no info currently set
|
||||
# TODO: optimize so that we only actually add that tracing if it's in
|
||||
# the new breakpoint context.
|
||||
additionalInfo = None
|
||||
try:
|
||||
additionalInfo = t.additionalInfo
|
||||
except AttributeError:
|
||||
pass # that's ok, no info currently set
|
||||
|
||||
if additionalInfo is not None:
|
||||
for frame in additionalInfo.IterFrames():
|
||||
if frame is not ignore_frame:
|
||||
self.SetTraceForFrameAndParents(frame, overwrite_prev_trace=overwrite_prev_trace)
|
||||
if additionalInfo is not None:
|
||||
for frame in additionalInfo.IterFrames():
|
||||
if frame is not ignore_frame:
|
||||
self.SetTraceForFrameAndParents(frame, overwrite_prev_trace=overwrite_prev_trace)
|
||||
finally:
|
||||
frame = None
|
||||
t = None
|
||||
@@ -565,7 +549,7 @@ class PyDB:
|
||||
|
||||
def consolidate_breakpoints(self, file, id_to_breakpoint, breakpoints):
|
||||
break_dict = {}
|
||||
for breakpoint_id, pybreakpoint in id_to_breakpoint.items():
|
||||
for breakpoint_id, pybreakpoint in DictIterItems(id_to_breakpoint):
|
||||
break_dict[pybreakpoint.line] = pybreakpoint
|
||||
|
||||
breakpoints[file] = break_dict
|
||||
@@ -586,14 +570,18 @@ class PyDB:
|
||||
)
|
||||
|
||||
if eb.notify_on_terminate:
|
||||
self.break_on_uncaught_exceptions[exception] = eb
|
||||
cp = self.break_on_uncaught_exceptions.copy()
|
||||
cp[exception] = eb
|
||||
if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
|
||||
pydev_log.error("Exceptions to hook on terminate: %s\n" % (self.break_on_uncaught_exceptions,))
|
||||
pydev_log.error("Exceptions to hook on terminate: %s\n" % (cp,))
|
||||
self.break_on_uncaught_exceptions = cp
|
||||
|
||||
if eb.notify_always:
|
||||
self.break_on_caught_exceptions[exception] = eb
|
||||
cp = self.break_on_caught_exceptions.copy()
|
||||
cp[exception] = eb
|
||||
if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
|
||||
pydev_log.error("Exceptions to hook always: %s\n" % (self.break_on_caught_exceptions,))
|
||||
pydev_log.error("Exceptions to hook always: %s\n" % (cp,))
|
||||
self.break_on_caught_exceptions = cp
|
||||
|
||||
return eb
|
||||
|
||||
@@ -626,7 +614,7 @@ class PyDB:
|
||||
it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before
|
||||
probably will give better performance).
|
||||
'''
|
||||
#print ID_TO_MEANING[str(cmd_id)], repr(text)
|
||||
#print(ID_TO_MEANING[str(cmd_id)], repr(text))
|
||||
|
||||
self._main_lock.acquire()
|
||||
try:
|
||||
@@ -868,7 +856,7 @@ class PyDB:
|
||||
id_to_pybreakpoint[breakpoint_id] = breakpoint
|
||||
self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
|
||||
|
||||
self.setTracingForUntracedContexts()
|
||||
self.setTracingForUntracedContexts(overwrite_prev_trace=True)
|
||||
|
||||
elif cmd_id == CMD_REMOVE_BREAK:
|
||||
#command to remove some breakpoint
|
||||
@@ -896,7 +884,7 @@ class PyDB:
|
||||
raise NameError(breakpoint_type)
|
||||
|
||||
try:
|
||||
id_to_pybreakpoint = file_to_id_to_breakpoint[file]
|
||||
id_to_pybreakpoint = file_to_id_to_breakpoint.get(file, {})
|
||||
if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
|
||||
existing = id_to_pybreakpoint[breakpoint_id]
|
||||
sys.stderr.write('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % (
|
||||
@@ -934,8 +922,8 @@ class PyDB:
|
||||
# which allows setting caught/uncaught per exception.
|
||||
#
|
||||
splitted = text.split(';')
|
||||
self.break_on_uncaught_exceptions.clear()
|
||||
self.break_on_caught_exceptions.clear()
|
||||
self.break_on_uncaught_exceptions = {}
|
||||
self.break_on_caught_exceptions = {}
|
||||
added = []
|
||||
if len(splitted) >= 4:
|
||||
if splitted[0] == 'true':
|
||||
@@ -1031,8 +1019,13 @@ class PyDB:
|
||||
elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
|
||||
exception = text
|
||||
try:
|
||||
DictPop(self.break_on_uncaught_exceptions, exception, None)
|
||||
DictPop(self.break_on_caught_exceptions, exception, None)
|
||||
cp = self.break_on_uncaught_exceptions.copy()
|
||||
DictPop(cp, exception, None)
|
||||
self.break_on_uncaught_exceptions = cp
|
||||
|
||||
cp = self.break_on_caught_exceptions.copy()
|
||||
DictPop(cp, exception, None)
|
||||
self.break_on_caught_exceptions = cp
|
||||
except:
|
||||
pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0]);
|
||||
update_exception_hook(self)
|
||||
@@ -1060,6 +1053,17 @@ class PyDB:
|
||||
except :
|
||||
pass
|
||||
|
||||
elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION:
|
||||
# Command which takes care for the debug console communication
|
||||
if text != "":
|
||||
thread_id, frame_id, console_command = text.split('\t', 2)
|
||||
console_command, line = console_command.split('\t')
|
||||
if console_command == 'EVALUATE':
|
||||
int_cmd = InternalEvaluateConsoleExpression(seq, thread_id, frame_id, line)
|
||||
elif console_command == 'GET_COMPLETIONS':
|
||||
int_cmd = InternalConsoleGetCompletions(seq, thread_id, frame_id, line)
|
||||
self.postInternalCommand(int_cmd, thread_id)
|
||||
|
||||
elif cmd_id == CMD_RUN_CUSTOM_OPERATION:
|
||||
# Command which runs a custom operation
|
||||
if text != "":
|
||||
@@ -1216,7 +1220,7 @@ class PyDB:
|
||||
try:
|
||||
from_this_thread = []
|
||||
|
||||
for frame_id, custom_frame in CustomFramesContainer.custom_frames.items():
|
||||
for frame_id, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
|
||||
if custom_frame.thread_id == thread.ident:
|
||||
# print >> sys.stderr, 'Frame created: ', frame_id
|
||||
self.writer.addCommand(self.cmdFactory.makeCustomFrameCreatedMessage(frame_id, custom_frame.name))
|
||||
@@ -1337,7 +1341,7 @@ class PyDB:
|
||||
if self._finishDebuggingSession and not self._terminationEventSent:
|
||||
#that was not working very well because jython gave some socket errors
|
||||
try:
|
||||
threads = threadingEnumerate()
|
||||
threads = DictKeys(PyDBDaemonThread.created_pydb_daemon_threads)
|
||||
for t in threads:
|
||||
if hasattr(t, 'doKillPydevThread'):
|
||||
t.doKillPydevThread()
|
||||
@@ -1350,10 +1354,10 @@ class PyDB:
|
||||
|
||||
is_file_to_ignore = DictContains(DONT_TRACE, base) #we don't want to debug threading or anything related to pydevd
|
||||
|
||||
#print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name, is_file_to_ignore)
|
||||
if is_file_to_ignore:
|
||||
return None
|
||||
|
||||
#print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name)
|
||||
try:
|
||||
#this shouldn't give an exception, but it could happen... (python bug)
|
||||
#see http://mail.python.org/pipermail/python-bugs-list/2007-June/038796.html
|
||||
@@ -1388,9 +1392,6 @@ class PyDB:
|
||||
self.processThreadNotAlive(GetThreadId(t))
|
||||
return None # suspend tracing
|
||||
|
||||
if is_file_to_ignore:
|
||||
return None
|
||||
|
||||
# each new frame...
|
||||
return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg)
|
||||
|
||||
@@ -1422,8 +1423,9 @@ class PyDB:
|
||||
|
||||
|
||||
|
||||
def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev_trace=False):
|
||||
dispatch_func = self.trace_dispatch
|
||||
def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev_trace=False, dispatch_func=None):
|
||||
if dispatch_func is None:
|
||||
dispatch_func = self.trace_dispatch
|
||||
|
||||
if also_add_to_passed_frame:
|
||||
self.update_trace(frame, dispatch_func, overwrite_prev_trace)
|
||||
@@ -1460,13 +1462,14 @@ class PyDB:
|
||||
net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.writer" id="-1"/></xml>')
|
||||
self.writer.addCommand(net)
|
||||
|
||||
pydevd_tracing.SetTrace(self.trace_dispatch)
|
||||
self.patch_threads()
|
||||
pydevd_tracing.SetTrace(self.trace_dispatch)
|
||||
|
||||
|
||||
PyDBCommandThread(self).start()
|
||||
PyDBCheckAliveThread(self).start()
|
||||
|
||||
|
||||
def patch_threads(self):
|
||||
try:
|
||||
# not available in jython!
|
||||
@@ -1474,11 +1477,8 @@ class PyDB:
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
thread.start_new_thread = pydev_start_new_thread
|
||||
thread.start_new = pydev_start_new_thread
|
||||
except:
|
||||
pass
|
||||
from pydev_monkey import patch_thread_modules
|
||||
patch_thread_modules()
|
||||
|
||||
|
||||
def run(self, file, globals=None, locals=None, set_trace=True):
|
||||
@@ -1549,64 +1549,6 @@ class PyDB:
|
||||
cmd = self.cmdFactory.makeExitMessage()
|
||||
self.writer.addCommand(cmd)
|
||||
|
||||
def wait_for_commands(self, globals):
|
||||
thread = threading.currentThread()
|
||||
frame = MyFrame()
|
||||
frame.f_globals = globals
|
||||
frame.f_locals = globals
|
||||
frame.f_lineno = -1
|
||||
frame.f_code = FCode(setup['file'], setup['file'])
|
||||
thread_id = GetThreadId(thread)
|
||||
# frame_id = addCustomFrame(frame, 'todo', GetThreadId(thread))
|
||||
cmd = self.cmdFactory.makeThreadSuspendMessage(thread_id, frame, CMD_CONSOLE_EXEC, '')
|
||||
self.writer.addCommand(cmd)
|
||||
while True:
|
||||
self.processInternalCommands()
|
||||
time.sleep(0.01)
|
||||
|
||||
class MyFrame:
|
||||
def __init__(
|
||||
self,
|
||||
frame,
|
||||
template_frame_file=None,
|
||||
template_frame_line=None):
|
||||
|
||||
if template_frame_file is None:
|
||||
template_frame_file = get_template_file_name(frame)
|
||||
|
||||
self.back_context = frame.f_locals['context']
|
||||
self.f_code = FCode('Django Template', template_frame_file)
|
||||
|
||||
if template_frame_line is None:
|
||||
template_frame_line = get_template_line(frame, template_frame_file)
|
||||
self.f_lineno = template_frame_line
|
||||
|
||||
self.f_back = frame
|
||||
self.f_globals = {}
|
||||
self.f_locals = self.collect_context()
|
||||
self.f_trace = None
|
||||
|
||||
def collect_context(self):
|
||||
res = {}
|
||||
try:
|
||||
for d in self.back_context.dicts:
|
||||
res.update(d)
|
||||
except AttributeError:
|
||||
pass
|
||||
return res
|
||||
|
||||
def changeVariable(self, name, value):
|
||||
for d in self.back_context.dicts:
|
||||
if DictContains(d, name):
|
||||
d[name] = value
|
||||
self.f_locals[name] = value
|
||||
|
||||
|
||||
class FCode:
|
||||
def __init__(self, name, filename):
|
||||
self.co_name = name
|
||||
self.co_filename = filename
|
||||
|
||||
def set_debug(setup):
|
||||
setup['DEBUG_RECORD_SOCKET_READS'] = True
|
||||
setup['DEBUG_TRACE_BREAKPOINTS'] = 1
|
||||
@@ -1624,47 +1566,47 @@ def processCommandLine(argv):
|
||||
setup['multiproc'] = False #Used by PyCharm (reuses connection: ssh tunneling)
|
||||
setup['multiprocess'] = False # Used by PyDev (creates new connection to ide)
|
||||
setup['save-signatures'] = False
|
||||
setup['cmd-line'] = False
|
||||
setup['print-in-debugger-startup'] = False
|
||||
i = 0
|
||||
del argv[0]
|
||||
while (i < len(argv)):
|
||||
if (argv[i] == '--port'):
|
||||
if argv[i] == '--port':
|
||||
del argv[i]
|
||||
setup['port'] = int(argv[i])
|
||||
del argv[i]
|
||||
elif (argv[i] == '--vm_type'):
|
||||
elif argv[i] == '--vm_type':
|
||||
del argv[i]
|
||||
setup['vm_type'] = argv[i]
|
||||
del argv[i]
|
||||
elif (argv[i] == '--client'):
|
||||
elif argv[i] == '--client':
|
||||
del argv[i]
|
||||
setup['client'] = argv[i]
|
||||
del argv[i]
|
||||
elif (argv[i] == '--server'):
|
||||
elif argv[i] == '--server':
|
||||
del argv[i]
|
||||
setup['server'] = True
|
||||
elif (argv[i] == '--file'):
|
||||
elif argv[i] == '--file':
|
||||
del argv[i]
|
||||
setup['file'] = argv[i]
|
||||
i = len(argv) # pop out, file is our last argument
|
||||
elif (argv[i] == '--DEBUG_RECORD_SOCKET_READS'):
|
||||
elif argv[i] == '--DEBUG_RECORD_SOCKET_READS':
|
||||
del argv[i]
|
||||
setup['DEBUG_RECORD_SOCKET_READS'] = True
|
||||
elif (argv[i] == '--DEBUG'):
|
||||
elif argv[i] == '--DEBUG':
|
||||
del argv[i]
|
||||
set_debug(setup)
|
||||
elif (argv[i] == '--multiproc'):
|
||||
elif argv[i] == '--multiproc':
|
||||
del argv[i]
|
||||
setup['multiproc'] = True
|
||||
elif (argv[i] == '--multiprocess'):
|
||||
elif argv[i] == '--multiprocess':
|
||||
del argv[i]
|
||||
setup['multiprocess'] = True
|
||||
elif (argv[i] == '--save-signatures'):
|
||||
elif argv[i] == '--save-signatures':
|
||||
del argv[i]
|
||||
setup['save-signatures'] = True
|
||||
elif (argv[i] == '--cmd-line'):
|
||||
elif argv[i] == '--print-in-debugger-startup':
|
||||
del argv[i]
|
||||
setup['cmd-line'] = True
|
||||
setup['print-in-debugger-startup'] = True
|
||||
else:
|
||||
raise ValueError("unexpected option " + argv[i])
|
||||
return setup
|
||||
@@ -1675,18 +1617,6 @@ def usage(doExit=0):
|
||||
if doExit:
|
||||
sys.exit(0)
|
||||
|
||||
def SetTraceForParents(frame, dispatch_func):
|
||||
frame = frame.f_back
|
||||
while frame:
|
||||
if frame.f_trace is None:
|
||||
frame.f_trace = dispatch_func
|
||||
|
||||
frame = frame.f_back
|
||||
del frame
|
||||
|
||||
def exit_hook():
|
||||
debugger = GetGlobalDebugger()
|
||||
debugger.exiting()
|
||||
|
||||
def initStdoutRedirect():
|
||||
if not getattr(sys, 'stdoutBuf', None):
|
||||
@@ -1751,7 +1681,7 @@ def settrace(
|
||||
|
||||
|
||||
|
||||
_set_trace_lock = threading.Lock()
|
||||
_set_trace_lock = _pydev_thread.allocate_lock()
|
||||
|
||||
def _locked_settrace(
|
||||
host,
|
||||
@@ -1806,7 +1736,7 @@ def _locked_settrace(
|
||||
|
||||
CustomFramesContainer.custom_frames_lock.acquire()
|
||||
try:
|
||||
for _frameId, custom_frame in CustomFramesContainer.custom_frames.items():
|
||||
for _frameId, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
|
||||
debugger.SetTraceForFrameAndParents(custom_frame.frame, False)
|
||||
finally:
|
||||
CustomFramesContainer.custom_frames_lock.release()
|
||||
@@ -1833,7 +1763,9 @@ def _locked_settrace(
|
||||
# As this is the first connection, also set tracing for any untraced threads
|
||||
debugger.setTracingForUntracedContexts(ignore_frame=GetFrame(), overwrite_prev_trace=overwrite_prev_trace)
|
||||
|
||||
sys.exitfunc = exit_hook
|
||||
# Stop the tracing as the last thing before the actual shutdown for a clean exit.
|
||||
atexit.register(stoptrace)
|
||||
|
||||
#Suspend as the last thing after all tracing is in place.
|
||||
if suspend:
|
||||
debugger.setSuspend(t, CMD_SET_BREAK)
|
||||
@@ -1876,21 +1808,17 @@ def stoptrace():
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
thread.start_new_thread = _original_start_new_thread
|
||||
thread.start_new = _original_start_new_thread
|
||||
except:
|
||||
pass
|
||||
|
||||
from pydev_monkey import undo_patch_thread_modules
|
||||
undo_patch_thread_modules()
|
||||
|
||||
debugger = GetGlobalDebugger()
|
||||
|
||||
|
||||
if debugger:
|
||||
debugger.trace_dispatch = None
|
||||
|
||||
debugger.SetTraceForFrameAndParents(GetFrame(), False)
|
||||
|
||||
|
||||
debugger.SetTraceForFrameAndParents(
|
||||
GetFrame(), also_add_to_passed_frame=True, overwrite_prev_trace=True, dispatch_func=lambda *args:None)
|
||||
debugger.exiting()
|
||||
|
||||
|
||||
killAllPydevThreads()
|
||||
|
||||
connected = False
|
||||
@@ -1981,6 +1909,7 @@ class SetupHolder:
|
||||
# main
|
||||
#=======================================================================================================================
|
||||
if __name__ == '__main__':
|
||||
|
||||
# parse the command line. --file is our last argument that is required
|
||||
try:
|
||||
sys.original_argv = sys.argv[:]
|
||||
@@ -1990,6 +1919,12 @@ if __name__ == '__main__':
|
||||
traceback.print_exc()
|
||||
usage(1)
|
||||
|
||||
if setup['print-in-debugger-startup']:
|
||||
try:
|
||||
pid = ' (pid: %s)' % os.getpid()
|
||||
except:
|
||||
pid = ''
|
||||
sys.stderr.write("pydev debugger: starting%s\n" % pid)
|
||||
|
||||
fix_getpass.fixGetpass()
|
||||
|
||||
@@ -2098,11 +2033,6 @@ if __name__ == '__main__':
|
||||
except:
|
||||
pass # It's ok not having stackless there...
|
||||
|
||||
debugger = PyDB()
|
||||
|
||||
if setup['cmd-line']:
|
||||
debugger.cmd_line = True
|
||||
|
||||
if fix_app_engine_debug:
|
||||
sys.stderr.write("pydev debugger: google app engine integration enabled\n")
|
||||
curr_dir = os.path.dirname(__file__)
|
||||
@@ -2115,8 +2045,10 @@ if __name__ == '__main__':
|
||||
sys.argv.insert(3, '--automatic_restart=no')
|
||||
sys.argv.insert(4, '--max_module_instances=1')
|
||||
|
||||
debugger = PyDB()
|
||||
# Run the dev_appserver
|
||||
debugger.run(setup['file'], None, None, set_trace=False)
|
||||
|
||||
else:
|
||||
# as to get here all our imports are already resolved, the psyco module can be
|
||||
# changed and we'll still get the speedups in the debugger, as those functions
|
||||
@@ -2132,11 +2064,14 @@ if __name__ == '__main__':
|
||||
import pydevd_psyco_stub
|
||||
sys.modules['psyco'] = pydevd_psyco_stub
|
||||
|
||||
debugger = PyDB()
|
||||
|
||||
if setup['save-signatures']:
|
||||
if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
|
||||
sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
|
||||
else:
|
||||
# Only import it if we're going to use it!
|
||||
from pydevd_signature import SignatureFactory
|
||||
debugger.signature_factory = SignatureFactory()
|
||||
|
||||
try:
|
||||
@@ -2149,8 +2084,4 @@ if __name__ == '__main__':
|
||||
connected = True # Mark that we're connected when started from inside ide.
|
||||
|
||||
debugger.run(setup['file'], None, None)
|
||||
|
||||
# if setup['cmd-line']:
|
||||
# debugger.wait_for_commands(globals)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import sys
|
||||
from pydevd_constants import * #@UnusedWildImport
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
from _pydev_imps import _pydev_thread
|
||||
from pydevd_frame import PyDBFrame
|
||||
import weakref
|
||||
|
||||
@@ -62,7 +59,7 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditional
|
||||
#Or if the user compiled threadframe (from http://www.majid.info/mylos/stories/2004/06/10/threadframe.html)
|
||||
|
||||
#NOT RLock!! (could deadlock if it was)
|
||||
self.lock = threading.Lock()
|
||||
self.lock = _pydev_thread.allocate_lock()
|
||||
self._acquire_lock = self.lock.acquire
|
||||
self._release_lock = self.lock.release
|
||||
|
||||
|
||||
@@ -8,10 +8,7 @@ _original_excepthook = None
|
||||
_handle_exceptions = None
|
||||
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
import _pydev_threading as threading
|
||||
|
||||
threadingCurrentThread = threading.currentThread
|
||||
|
||||
@@ -145,7 +142,7 @@ def _restore_pm_excepthook():
|
||||
|
||||
def update_exception_hook(dbg):
|
||||
if dbg.break_on_uncaught_exceptions:
|
||||
_set_pm_excepthook(dbg.break_on_uncaught_exceptions.copy())
|
||||
_set_pm_excepthook(dbg.break_on_uncaught_exceptions)
|
||||
else:
|
||||
_restore_pm_excepthook()
|
||||
|
||||
|
||||
@@ -61,32 +61,11 @@ from pydevd_constants import * #@UnusedWildImport
|
||||
|
||||
import sys
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_time as time
|
||||
import _pydev_threading as threading
|
||||
try:
|
||||
import _pydev_thread as thread
|
||||
except ImportError:
|
||||
import _thread as thread #Py3K changed it.
|
||||
import _pydev_Queue as _queue
|
||||
from _pydev_socket import socket
|
||||
from _pydev_socket import AF_INET, SOCK_STREAM
|
||||
from _pydev_socket import SHUT_RD, SHUT_WR
|
||||
else:
|
||||
import time
|
||||
import threading
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
import _thread as thread #Py3K changed it.
|
||||
|
||||
try:
|
||||
import Queue as _queue
|
||||
except ImportError:
|
||||
import queue as _queue
|
||||
from socket import socket
|
||||
from socket import AF_INET, SOCK_STREAM
|
||||
from socket import SHUT_RD, SHUT_WR
|
||||
from _pydev_imps import _pydev_time as time, _pydev_thread
|
||||
from _pydev_imps import _pydev_thread as thread
|
||||
import _pydev_threading as threading
|
||||
from _pydev_imps._pydev_socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR
|
||||
from pydev_imports import _queue
|
||||
|
||||
try:
|
||||
from urllib import quote, quote_plus, unquote, unquote_plus
|
||||
@@ -103,6 +82,8 @@ import pydev_log
|
||||
import _pydev_completer
|
||||
|
||||
from pydevd_tracing import GetExceptionTracebackStr
|
||||
import pydevd_console
|
||||
from pydev_monkey import disable_trace_thread_modules, enable_trace_thread_modules
|
||||
|
||||
|
||||
|
||||
@@ -262,22 +243,42 @@ def SetGlobalDebugger(dbg):
|
||||
#=======================================================================================================================
|
||||
# PyDBDaemonThread
|
||||
#=======================================================================================================================
|
||||
class PyDBDaemonThread(threading.Thread):
|
||||
class PyDBDaemonThread:
|
||||
|
||||
created_pydb_daemon_threads = {}
|
||||
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
self.setDaemon(True)
|
||||
# Note: subclasses are always daemon threads.
|
||||
self.killReceived = False
|
||||
self.dontTraceMe = True
|
||||
|
||||
def run(self):
|
||||
if sys.platform.startswith("java"):
|
||||
import org.python.core as PyCore #@UnresolvedImport
|
||||
ss = PyCore.PySystemState()
|
||||
# Note: Py.setSystemState() affects only the current thread.
|
||||
PyCore.Py.setSystemState(ss)
|
||||
def setName(self, name):
|
||||
self.name = name
|
||||
|
||||
self.OnRun()
|
||||
def start(self):
|
||||
import pydev_monkey
|
||||
start_new_thread = pydev_monkey.get_original_start_new_thread(_pydev_thread)
|
||||
start_new_thread(self.run, ())
|
||||
|
||||
def run(self):
|
||||
created_pydb_daemon = self.created_pydb_daemon_threads
|
||||
created_pydb_daemon[self] = 1
|
||||
dummy_thread = threading.currentThread()
|
||||
dummy_thread.is_pydev_daemon_thread = True
|
||||
try:
|
||||
try:
|
||||
if IS_JYTHON:
|
||||
import org.python.core as PyCore #@UnresolvedImport
|
||||
ss = PyCore.PySystemState()
|
||||
# Note: Py.setSystemState() affects only the current thread.
|
||||
PyCore.Py.setSystemState(ss)
|
||||
|
||||
self.OnRun()
|
||||
except:
|
||||
if sys is not None and traceback is not None:
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
del created_pydb_daemon[self]
|
||||
|
||||
def OnRun(self):
|
||||
raise NotImplementedError('Should be reimplemented by: %s' % self.__class__)
|
||||
@@ -288,7 +289,18 @@ class PyDBDaemonThread(threading.Thread):
|
||||
|
||||
def stopTrace(self):
|
||||
if self.dontTraceMe:
|
||||
pydevd_tracing.SetTrace(None) # no debugging on this thread
|
||||
|
||||
disable_tracing = True
|
||||
|
||||
if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON and sys.hexversion <= 0x020201f0:
|
||||
# don't run untraced threads if we're in jython 2.2.1 or lower
|
||||
# jython bug: if we start a thread and another thread changes the tracing facility
|
||||
# it affects other threads (it's not set only for the thread but globally)
|
||||
# Bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1870039&group_id=12867&atid=112867
|
||||
disable_tracing = False
|
||||
|
||||
if disable_tracing:
|
||||
pydevd_tracing.SetTrace(None) # no debugging on this thread
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
@@ -371,7 +383,6 @@ class WriterThread(PyDBDaemonThread):
|
||||
""" writer thread writes out the commands in an infinite loop """
|
||||
def __init__(self, sock):
|
||||
PyDBDaemonThread.__init__(self)
|
||||
self.setDaemon(False) #writer isn't daemon to be able to deliver all messages after main thread terminated
|
||||
self.sock = sock
|
||||
self.setName("pydevd.Writer")
|
||||
self.cmdQueue = _queue.Queue()
|
||||
@@ -389,11 +400,16 @@ class WriterThread(PyDBDaemonThread):
|
||||
""" just loop and write responses """
|
||||
|
||||
self.stopTrace()
|
||||
get_has_timeout = sys.hexversion >= 0x02030000 # 2.3 onwards have it.
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
try:
|
||||
cmd = self.cmdQueue.get(1, 0.1)
|
||||
if get_has_timeout:
|
||||
cmd = self.cmdQueue.get(1, 0.1)
|
||||
else:
|
||||
time.sleep(.01)
|
||||
cmd = self.cmdQueue.get(0)
|
||||
except _queue.Empty:
|
||||
if self.killReceived:
|
||||
try:
|
||||
@@ -790,7 +806,7 @@ class ReloadCodeCommand(InternalThreadCommand):
|
||||
self.thread_id = thread_id
|
||||
self.module_name = module_name
|
||||
self.executed = False
|
||||
self.lock = threading.Lock()
|
||||
self.lock = _pydev_thread.allocate_lock()
|
||||
|
||||
|
||||
def canBeExecutedBy(self, thread_id):
|
||||
@@ -1008,7 +1024,7 @@ class InternalEvaluateExpression(InternalThreadCommand):
|
||||
try:
|
||||
result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec)
|
||||
xml = "<xml>"
|
||||
xml += pydevd_vars.varToXML(result, "", self.doTrim)
|
||||
xml += pydevd_vars.varToXML(result, self.expression, self.doTrim)
|
||||
xml += "</xml>"
|
||||
cmd = dbg.cmdFactory.makeEvaluateExpressionMessage(self.sequence, xml)
|
||||
dbg.writer.addCommand(cmd)
|
||||
@@ -1168,7 +1184,12 @@ class InternalEvaluateConsoleExpression(InternalThreadCommand):
|
||||
console_message = pydevd_console.execute_console_command(frame, self.thread_id, self.frame_id, self.line)
|
||||
cmd = dbg.cmdFactory.makeSendConsoleMessage(self.sequence, console_message.toXML())
|
||||
else:
|
||||
console_message.add_console_message(pydevd_console.CONSOLE_ERROR, "Select the valid frame in the debug view")
|
||||
from pydevd_console import ConsoleMessage
|
||||
console_message = ConsoleMessage()
|
||||
console_message.add_console_message(
|
||||
pydevd_console.CONSOLE_ERROR,
|
||||
"Select the valid frame in the debug view (thread: %s, frame: %s invalid)" % (self.thread_id, self.frame_id),
|
||||
)
|
||||
cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, console_message.toXML())
|
||||
except:
|
||||
exc = GetExceptionTracebackStr()
|
||||
@@ -1245,13 +1266,10 @@ class InternalConsoleExec(InternalThreadCommand):
|
||||
|
||||
def doIt(self, dbg):
|
||||
""" Converts request into python variable """
|
||||
pydev_start_new_thread = None
|
||||
try:
|
||||
try:
|
||||
pydev_start_new_thread = thread.start_new_thread
|
||||
|
||||
thread.start_new_thread = thread._original_start_new_thread #don't trace new threads created by console command
|
||||
thread.start_new = thread._original_start_new_thread
|
||||
#don't trace new threads created by console command
|
||||
disable_trace_thread_modules()
|
||||
|
||||
result = pydevconsole.consoleExec(self.thread_id, self.frame_id, self.expression)
|
||||
xml = "<xml>"
|
||||
@@ -1265,8 +1283,8 @@ class InternalConsoleExec(InternalThreadCommand):
|
||||
cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating console expression " + exc)
|
||||
dbg.writer.addCommand(cmd)
|
||||
finally:
|
||||
thread.start_new_thread = pydev_start_new_thread
|
||||
thread.start_new = pydev_start_new_thread
|
||||
enable_trace_thread_modules()
|
||||
|
||||
sys.stderr.flush()
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ class ConsoleMessage:
|
||||
self.more = False
|
||||
# List of tuple [('error', 'error_message'), ('message_list', 'output_message')]
|
||||
self.console_messages = []
|
||||
|
||||
|
||||
def add_console_message(self, message_type, message):
|
||||
"""add messages in the console_messages list
|
||||
"""add messages in the console_messages list
|
||||
"""
|
||||
for m in message.split("\n"):
|
||||
if m.strip():
|
||||
@@ -50,14 +50,14 @@ class ConsoleMessage:
|
||||
</xml>
|
||||
"""
|
||||
makeValid = makeValidXmlValue
|
||||
|
||||
|
||||
xml = '<xml><more>%s</more>' % (self.more)
|
||||
|
||||
for message_type, message in self.console_messages:
|
||||
xml += '<%s message="%s"></%s>' % (message_type, makeValid(message), message_type)
|
||||
|
||||
xml += '</xml>'
|
||||
|
||||
|
||||
return xml
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class ConsoleMessage:
|
||||
# DebugConsoleStdIn
|
||||
#=======================================================================================================================
|
||||
class DebugConsoleStdIn(BaseStdIn):
|
||||
|
||||
|
||||
overrides(BaseStdIn.readline)
|
||||
def readline(self, *args, **kwargs):
|
||||
sys.stderr.write('Warning: Reading from stdin is still not supported in this console.\n')
|
||||
@@ -75,10 +75,10 @@ class DebugConsoleStdIn(BaseStdIn):
|
||||
# DebugConsole
|
||||
#=======================================================================================================================
|
||||
class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
|
||||
"""Wrapper around code.InteractiveConsole, in order to send
|
||||
"""Wrapper around code.InteractiveConsole, in order to send
|
||||
errors and outputs to the debug console
|
||||
"""
|
||||
|
||||
|
||||
overrides(BaseInterpreterInterface.createStdIn)
|
||||
def createStdIn(self):
|
||||
return DebugConsoleStdIn() #For now, raw_input is not supported in this console.
|
||||
@@ -86,12 +86,12 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
|
||||
|
||||
overrides(InteractiveConsole.push)
|
||||
def push(self, line, frame):
|
||||
"""Change built-in stdout and stderr methods by the
|
||||
"""Change built-in stdout and stderr methods by the
|
||||
new custom StdMessage.
|
||||
execute the InteractiveConsole.push.
|
||||
Change the stdout and stderr back be the original built-ins
|
||||
|
||||
Return boolean (True if more input is required else False),
|
||||
|
||||
Return boolean (True if more input is required else False),
|
||||
output_messages and input_messages
|
||||
"""
|
||||
more = False
|
||||
@@ -102,7 +102,7 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
|
||||
self.frame = frame
|
||||
out = sys.stdout = IOBuf()
|
||||
err = sys.stderr = IOBuf()
|
||||
more, _need_input = self.addExec(line)
|
||||
more = self.addExec(line)
|
||||
except Exception:
|
||||
exc = GetExceptionTracebackStr()
|
||||
err.buflist.append("Internal Error: %s" % (exc,))
|
||||
@@ -111,15 +111,15 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
|
||||
self.frame = None
|
||||
frame = None
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
sys.stderr = original_stderr
|
||||
|
||||
return more, out.buflist, err.buflist
|
||||
|
||||
|
||||
|
||||
|
||||
overrides(BaseInterpreterInterface.doAddExec)
|
||||
def doAddExec(self, line):
|
||||
return InteractiveConsole.push(self, line)
|
||||
|
||||
|
||||
|
||||
overrides(InteractiveConsole.runcode)
|
||||
def runcode(self, code):
|
||||
@@ -147,24 +147,24 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
|
||||
# InteractiveConsoleCache
|
||||
#=======================================================================================================================
|
||||
class InteractiveConsoleCache:
|
||||
|
||||
|
||||
thread_id = None
|
||||
frame_id = None
|
||||
interactive_console_instance = None
|
||||
|
||||
|
||||
|
||||
#Note: On Jython 2.1 we can't use classmethod or staticmethod, so, just make the functions below free-functions.
|
||||
def get_interactive_console(thread_id, frame_id, frame, console_message):
|
||||
"""returns the global interactive console.
|
||||
interactive console should have been initialized by this time
|
||||
interactive console should have been initialized by this time
|
||||
"""
|
||||
if InteractiveConsoleCache.thread_id == thread_id and InteractiveConsoleCache.frame_id == frame_id:
|
||||
return InteractiveConsoleCache.interactive_console_instance
|
||||
|
||||
|
||||
InteractiveConsoleCache.interactive_console_instance = DebugConsole()
|
||||
InteractiveConsoleCache.thread_id = thread_id
|
||||
InteractiveConsoleCache.thread_id = thread_id
|
||||
InteractiveConsoleCache.frame_id = frame_id
|
||||
|
||||
|
||||
console_stacktrace = traceback.extract_stack(frame, limit=1)
|
||||
if console_stacktrace:
|
||||
current_context = console_stacktrace[0] # top entry from stacktrace
|
||||
@@ -177,23 +177,23 @@ def clear_interactive_console():
|
||||
InteractiveConsoleCache.thread_id = None
|
||||
InteractiveConsoleCache.frame_id = None
|
||||
InteractiveConsoleCache.interactive_console_instance = None
|
||||
|
||||
|
||||
|
||||
def execute_console_command(frame, thread_id, frame_id, line):
|
||||
"""fetch an interactive console instance from the cache and
|
||||
"""fetch an interactive console instance from the cache and
|
||||
push the received command to the console.
|
||||
|
||||
create and return an instance of console_message
|
||||
|
||||
create and return an instance of console_message
|
||||
"""
|
||||
console_message = ConsoleMessage()
|
||||
|
||||
|
||||
interpreter = get_interactive_console(thread_id, frame_id, frame, console_message)
|
||||
more, output_messages, error_messages = interpreter.push(line, frame)
|
||||
console_message.update_more(more)
|
||||
|
||||
|
||||
for message in output_messages:
|
||||
console_message.add_console_message(CONSOLE_OUTPUT, message)
|
||||
|
||||
|
||||
for message in error_messages:
|
||||
console_message.add_console_message(CONSOLE_ERROR, message)
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'''
|
||||
This module holds the constants used for specifying the states of the debugger.
|
||||
'''
|
||||
|
||||
STATE_RUN = 1
|
||||
STATE_SUSPEND = 2
|
||||
|
||||
@@ -73,13 +72,10 @@ except AttributeError:
|
||||
SUPPORT_GEVENT = os.getenv('GEVENT_SUPPORT', 'False') == 'True'
|
||||
|
||||
USE_LIB_COPY = SUPPORT_GEVENT and not IS_PY3K and sys.version_info[1] >= 6
|
||||
import _pydev_threading as threading
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
|
||||
_nextThreadIdLock = threading.Lock()
|
||||
from _pydev_imps import _pydev_thread
|
||||
_nextThreadIdLock = _pydev_thread.allocate_lock()
|
||||
|
||||
#=======================================================================================================================
|
||||
# Jython?
|
||||
@@ -119,20 +115,40 @@ if IS_PY3K:
|
||||
return list(d.values())
|
||||
|
||||
DictIterValues = dict.values
|
||||
|
||||
def DictIterItems(d):
|
||||
return d.items()
|
||||
|
||||
def DictItems(d):
|
||||
return list(d.items())
|
||||
|
||||
else:
|
||||
DictKeys = dict.keys
|
||||
try:
|
||||
DictIterValues = dict.itervalues
|
||||
except:
|
||||
DictIterValues = dict.values #Older versions don't have the itervalues
|
||||
|
||||
DictValues = dict.values
|
||||
|
||||
def DictIterItems(d):
|
||||
return d.iteritems()
|
||||
|
||||
def DictItems(d):
|
||||
return d.items()
|
||||
|
||||
|
||||
try:
|
||||
xrange
|
||||
xrange = xrange
|
||||
except:
|
||||
#Python 3k does not have it
|
||||
xrange = range
|
||||
|
||||
try:
|
||||
import itertools
|
||||
izip = itertools.izip
|
||||
except:
|
||||
izip = zip
|
||||
|
||||
try:
|
||||
object
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from pydevd_constants import * #@UnusedWildImport
|
||||
from pydevd_file_utils import GetFilenameAndBase
|
||||
from _pydev_imps import _pydev_thread
|
||||
threadingCurrentThread = threading.currentThread
|
||||
|
||||
DEBUG = False
|
||||
@@ -13,7 +14,7 @@ class CustomFramesContainer:
|
||||
|
||||
def CustomFramesContainerInit(): #Note: no staticmethod on jython 2.1 (so, use free-function)
|
||||
|
||||
CustomFramesContainer.custom_frames_lock = threading.Lock()
|
||||
CustomFramesContainer.custom_frames_lock = _pydev_thread.allocate_lock()
|
||||
|
||||
# custom_frames can only be accessed if properly locked with custom_frames_lock!
|
||||
# Key is a string identifying the frame (as well as the thread it belongs to).
|
||||
|
||||
@@ -15,7 +15,11 @@ from pydevd_comm import CMD_ADD_DJANGO_EXCEPTION_BREAK, \
|
||||
CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT
|
||||
from pydevd_constants import * # @UnusedWildImport
|
||||
from pydevd_file_utils import GetFilenameAndBase
|
||||
from pydevd_signature import sendSignatureCallTrace
|
||||
try:
|
||||
from pydevd_signature import sendSignatureCallTrace
|
||||
except ImportError:
|
||||
def sendSignatureCallTrace(*args, **kwargs):
|
||||
pass
|
||||
import pydevd_vars
|
||||
import pydevd_dont_trace
|
||||
|
||||
@@ -81,7 +85,7 @@ class PyDBFrame:
|
||||
|
||||
if trace is not None: #on jython trace is None on the first event
|
||||
exception_breakpoint = get_exception_breakpoint(
|
||||
exception, mainDebugger.break_on_caught_exceptions.copy())
|
||||
exception, mainDebugger.break_on_caught_exceptions)
|
||||
|
||||
if exception_breakpoint is not None:
|
||||
if not exception_breakpoint.notify_on_first_raise_only or just_raised(trace):
|
||||
@@ -203,6 +207,7 @@ class PyDBFrame:
|
||||
|
||||
try:
|
||||
frame_id_to_frame = {}
|
||||
frame_id_to_frame[id(frame)] = frame
|
||||
f = trace_obj.tb_frame
|
||||
while f is not None:
|
||||
frame_id_to_frame[id(f)] = f
|
||||
@@ -244,7 +249,7 @@ class PyDBFrame:
|
||||
if getattr(thread, 'pydev_do_not_trace', None):
|
||||
return None
|
||||
|
||||
if event == 'call':
|
||||
if event == 'call' and main_debugger.signature_factory:
|
||||
sendSignatureCallTrace(main_debugger, frame, filename)
|
||||
|
||||
is_exception_event = event == 'exception'
|
||||
@@ -403,12 +408,6 @@ class PyDBFrame:
|
||||
if stop:
|
||||
self.setSuspend(thread, CMD_SET_BREAK)
|
||||
|
||||
if event == 'return':
|
||||
if main_debugger.cmd_line:
|
||||
base = basename(back.f_code.co_filename)
|
||||
if base == 'pydevd.py' and back.f_code.co_name == 'run':
|
||||
self.setSuspend(thread, CMD_SET_BREAK) # we suspend on exit
|
||||
|
||||
# if thread has a suspend flag, we suspend with a busy wait
|
||||
if info.pydev_state == STATE_SUSPEND:
|
||||
self.doWaitSuspend(thread, frame, event, arg)
|
||||
|
||||
@@ -13,9 +13,13 @@ except:
|
||||
setattr(__builtin__, 'False', 0)
|
||||
|
||||
import pydevd_constants
|
||||
from pydevd_constants import DictIterItems, xrange
|
||||
|
||||
|
||||
MAX_ITEMS_TO_HANDLE = 500
|
||||
# Note: 300 is already a lot to see in the outline (after that the user should really use the shell to get things)
|
||||
# and this also means we'll pass less information to the client side (which makes debugging faster).
|
||||
MAX_ITEMS_TO_HANDLE = 300
|
||||
|
||||
TOO_LARGE_MSG = 'Too large to show contents. Max items to show: ' + str(MAX_ITEMS_TO_HANDLE)
|
||||
TOO_LARGE_ATTR = 'Unable to handle:'
|
||||
|
||||
@@ -58,7 +62,7 @@ except:
|
||||
class AbstractResolver:
|
||||
'''
|
||||
This class exists only for documentation purposes to explain how to create a resolver.
|
||||
|
||||
|
||||
Some examples on how to resolve things:
|
||||
- list: getDictionary could return a dict with index->item and use the index to resolve it later
|
||||
- set: getDictionary could return a dict with id(object)->object and reiterate in that array to resolve it later
|
||||
@@ -69,7 +73,7 @@ class AbstractResolver:
|
||||
'''
|
||||
In this method, we'll resolve some child item given the string representation of the item in the key
|
||||
representing the previously asked dictionary.
|
||||
|
||||
|
||||
@param var: this is the actual variable to be resolved.
|
||||
@param attribute: this is the string representation of a key previously returned in getDictionary.
|
||||
'''
|
||||
@@ -78,7 +82,7 @@ class AbstractResolver:
|
||||
def getDictionary(self, var):
|
||||
'''
|
||||
@param var: this is the variable that should have its children gotten.
|
||||
|
||||
|
||||
@return: a dictionary where each pair key, value should be shown to the user as children items
|
||||
in the variables view for the given var.
|
||||
'''
|
||||
@@ -128,12 +132,12 @@ class DefaultResolver:
|
||||
|
||||
declaredMethods = obj.getDeclaredMethods()
|
||||
declaredFields = obj.getDeclaredFields()
|
||||
for i in range(len(declaredMethods)):
|
||||
for i in xrange(len(declaredMethods)):
|
||||
name = declaredMethods[i].getName()
|
||||
ret[name] = declaredMethods[i].toString()
|
||||
found.put(name, 1)
|
||||
|
||||
for i in range(len(declaredFields)):
|
||||
for i in xrange(len(declaredFields)):
|
||||
name = declaredFields[i].getName()
|
||||
found.put(name, 1)
|
||||
#if declaredFields[i].isAccessible():
|
||||
@@ -145,7 +149,7 @@ class DefaultResolver:
|
||||
ret[name] = declaredFields[i].toString()
|
||||
|
||||
#this simple dir does not always get all the info, that's why we have the part before
|
||||
#(e.g.: if we do a dir on String, some methods that are from other interfaces such as
|
||||
#(e.g.: if we do a dir on String, some methods that are from other interfaces such as
|
||||
#charAt don't appear)
|
||||
try:
|
||||
d = dir(original)
|
||||
@@ -169,8 +173,8 @@ class DefaultResolver:
|
||||
names = var.__members__
|
||||
d = {}
|
||||
|
||||
#Be aware that the order in which the filters are applied attempts to
|
||||
#optimize the operation by removing as many items as possible in the
|
||||
#Be aware that the order in which the filters are applied attempts to
|
||||
#optimize the operation by removing as many items as possible in the
|
||||
#first filters, leaving fewer items for later filters
|
||||
|
||||
if filterBuiltIn or filterFunction:
|
||||
@@ -212,18 +216,18 @@ class DefaultResolver:
|
||||
class DictResolver:
|
||||
|
||||
def resolve(self, dict, key):
|
||||
if key == '__len__':
|
||||
if key in ('__len__', TOO_LARGE_ATTR):
|
||||
return None
|
||||
|
||||
if '(' not in key:
|
||||
#we have to treat that because the dict resolver is also used to directly resolve the global and local
|
||||
#scopes (which already have the items directly)
|
||||
#scopes (which already have the items directly)
|
||||
return dict[key]
|
||||
|
||||
#ok, we have to iterate over the items to find the one that matches the id, because that's the only way
|
||||
#to actually find the reference from the string we have before.
|
||||
expected_id = int(key.split('(')[-1][:-1])
|
||||
for key, val in dict.items():
|
||||
for key, val in DictIterItems(dict):
|
||||
if id(key) == expected_id:
|
||||
return val
|
||||
|
||||
@@ -241,10 +245,15 @@ class DictResolver:
|
||||
def getDictionary(self, dict):
|
||||
ret = {}
|
||||
|
||||
for key, val in dict.items():
|
||||
i = 0
|
||||
for key, val in DictIterItems(dict):
|
||||
i += 1
|
||||
#we need to add the id because otherwise we cannot find the real object to get its contents later on.
|
||||
key = '%s (%s)' % (self.keyStr(key), id(key))
|
||||
ret[key] = val
|
||||
if i > MAX_ITEMS_TO_HANDLE:
|
||||
ret[TOO_LARGE_ATTR] = TOO_LARGE_MSG
|
||||
break
|
||||
|
||||
ret['__len__'] = len(dict)
|
||||
return ret
|
||||
@@ -261,24 +270,25 @@ class TupleResolver: #to enumerate tuples and lists
|
||||
@param var: that's the original attribute
|
||||
@param attribute: that's the key passed in the dict (as a string)
|
||||
'''
|
||||
if attribute == '__len__' or attribute == TOO_LARGE_ATTR:
|
||||
if attribute in ('__len__', TOO_LARGE_ATTR):
|
||||
return None
|
||||
return var[int(attribute)]
|
||||
|
||||
def getDictionary(self, var):
|
||||
#return dict( [ (i, x) for i, x in enumerate(var) ] )
|
||||
# modified 'cause jython does not have enumerate support
|
||||
l = len(var)
|
||||
d = {}
|
||||
|
||||
if l < MAX_ITEMS_TO_HANDLE:
|
||||
format = '%0' + str(int(len(str(l)))) + 'd'
|
||||
|
||||
format_str = '%0' + str(int(len(str(l)))) + 'd'
|
||||
|
||||
i = 0
|
||||
for item in var:
|
||||
d[format_str % i] = item
|
||||
i += 1
|
||||
|
||||
|
||||
for i, item in zip(range(l), var):
|
||||
d[ format % i ] = item
|
||||
else:
|
||||
d[TOO_LARGE_ATTR] = TOO_LARGE_MSG
|
||||
if i > MAX_ITEMS_TO_HANDLE:
|
||||
d[TOO_LARGE_ATTR] = TOO_LARGE_MSG
|
||||
break
|
||||
|
||||
d['__len__'] = len(var)
|
||||
return d
|
||||
|
||||
@@ -293,7 +303,7 @@ class SetResolver:
|
||||
'''
|
||||
|
||||
def resolve(self, var, attribute):
|
||||
if attribute == '__len__':
|
||||
if attribute in ('__len__', TOO_LARGE_ATTR):
|
||||
return None
|
||||
|
||||
attribute = int(attribute)
|
||||
@@ -305,8 +315,16 @@ class SetResolver:
|
||||
|
||||
def getDictionary(self, var):
|
||||
d = {}
|
||||
i = 0
|
||||
for item in var:
|
||||
d[ id(item) ] = item
|
||||
i+= 1
|
||||
d[id(item)] = item
|
||||
|
||||
if i > MAX_ITEMS_TO_HANDLE:
|
||||
d[TOO_LARGE_ATTR] = TOO_LARGE_MSG
|
||||
break
|
||||
|
||||
|
||||
d['__len__'] = len(var)
|
||||
return d
|
||||
|
||||
@@ -325,7 +343,7 @@ class InstanceResolver:
|
||||
ret = {}
|
||||
|
||||
declaredFields = obj.__class__.getDeclaredFields()
|
||||
for i in range(len(declaredFields)):
|
||||
for i in xrange(len(declaredFields)):
|
||||
name = declaredFields[i].getName()
|
||||
try:
|
||||
declaredFields[i].setAccessible(True)
|
||||
@@ -352,7 +370,7 @@ class JyArrayResolver:
|
||||
def getDictionary(self, obj):
|
||||
ret = {}
|
||||
|
||||
for i in range(len(obj)):
|
||||
for i in xrange(len(obj)):
|
||||
ret[ i ] = obj[i]
|
||||
|
||||
ret['__len__'] = len(obj)
|
||||
@@ -367,13 +385,24 @@ class NdArrayResolver:
|
||||
This resolves a numpy ndarray returning some metadata about the NDArray
|
||||
'''
|
||||
|
||||
def is_numeric(self, obj):
|
||||
if not hasattr(obj, 'dtype'):
|
||||
return False
|
||||
return obj.dtype.kind in 'biufc'
|
||||
|
||||
def resolve(self, obj, attribute):
|
||||
if attribute == '__internals__':
|
||||
return defaultResolver.getDictionary(obj)
|
||||
if attribute == 'min':
|
||||
return obj.min()
|
||||
if self.is_numeric(obj):
|
||||
return obj.min()
|
||||
else:
|
||||
return None
|
||||
if attribute == 'max':
|
||||
return obj.max()
|
||||
if self.is_numeric(obj):
|
||||
return obj.max()
|
||||
else:
|
||||
return None
|
||||
if attribute == 'shape':
|
||||
return obj.shape
|
||||
if attribute == 'dtype':
|
||||
@@ -389,8 +418,12 @@ class NdArrayResolver:
|
||||
ret['min'] = 'ndarray too big, calculating min would slow down debugging'
|
||||
ret['max'] = 'ndarray too big, calculating max would slow down debugging'
|
||||
else:
|
||||
ret['min'] = obj.min()
|
||||
ret['max'] = obj.max()
|
||||
if self.is_numeric(obj):
|
||||
ret['min'] = obj.min()
|
||||
ret['max'] = obj.max()
|
||||
else:
|
||||
ret['min'] = 'not a numeric object'
|
||||
ret['max'] = 'not a numeric object'
|
||||
ret['shape'] = obj.shape
|
||||
ret['dtype'] = obj.dtype
|
||||
ret['size'] = obj.size
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import inspect
|
||||
import trace
|
||||
import os
|
||||
|
||||
trace._warn = lambda *args: None # workaround for http://bugs.python.org/issue17143 (PY-8706)
|
||||
try:
|
||||
import trace
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
trace._warn = lambda *args: None # workaround for http://bugs.python.org/issue17143 (PY-8706)
|
||||
|
||||
import gc
|
||||
from pydevd_comm import CMD_SIGNATURE_CALL_TRACE, NetCommand
|
||||
import pydevd_vars
|
||||
from pydevd_constants import xrange
|
||||
|
||||
class Signature(object):
|
||||
def __init__(self, file, name):
|
||||
@@ -43,7 +49,7 @@ class SignatureFactory(object):
|
||||
locals = frame.f_locals
|
||||
filename, modulename, funcname = self.file_module_function_of(frame)
|
||||
res = Signature(filename, funcname)
|
||||
for i in range(0, code.co_argcount):
|
||||
for i in xrange(0, code.co_argcount):
|
||||
name = code.co_varnames[i]
|
||||
tp = type(locals[name])
|
||||
class_name = tp.__name__
|
||||
@@ -123,9 +129,8 @@ def create_signature_message(signature):
|
||||
return NetCommand(CMD_SIGNATURE_CALL_TRACE, 0, cmdText)
|
||||
|
||||
def sendSignatureCallTrace(dbg, frame, filename):
|
||||
if dbg.signature_factory:
|
||||
if dbg.signature_factory.is_in_scope(filename):
|
||||
dbg.writer.addCommand(create_signature_message(dbg.signature_factory.create_signature(frame)))
|
||||
if dbg.signature_factory.is_in_scope(filename):
|
||||
dbg.writer.addCommand(create_signature_message(dbg.signature_factory.create_signature(frame)))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from pydevd_comm import GetGlobalDebugger
|
||||
import weakref
|
||||
from pydevd_file_utils import GetFilenameAndBase
|
||||
from pydevd import DONT_TRACE
|
||||
from pydevd_constants import DictItems
|
||||
|
||||
|
||||
# Used so that we don't loose the id (because we'll remove when it's not alive and would generate a new id for the
|
||||
@@ -195,7 +196,7 @@ def _schedule_callback(prev, next):
|
||||
register_tasklet_info(prev)
|
||||
|
||||
try:
|
||||
for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy!
|
||||
for tasklet_ref, tasklet_info in DictItems(_weak_tasklet_registered_to_info): # Make sure it's a copy!
|
||||
tasklet = tasklet_ref()
|
||||
if tasklet is None or not tasklet.alive:
|
||||
# Garbage-collected already!
|
||||
@@ -269,7 +270,7 @@ if not hasattr(stackless.tasklet, "trace_function"):
|
||||
register_tasklet_info(prev)
|
||||
|
||||
try:
|
||||
for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy!
|
||||
for tasklet_ref, tasklet_info in DictItems(_weak_tasklet_registered_to_info): # Make sure it's a copy!
|
||||
tasklet = tasklet_ref()
|
||||
if tasklet is None or not tasklet.alive:
|
||||
# Garbage-collected already!
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from pydevd_constants import * #@UnusedWildImport
|
||||
from _pydev_imps import _pydev_thread
|
||||
|
||||
try:
|
||||
import cStringIO as StringIO #may not always be available @UnusedImport
|
||||
@@ -8,10 +9,6 @@ except:
|
||||
except:
|
||||
import io as StringIO
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
|
||||
import sys #@Reimport
|
||||
import traceback
|
||||
@@ -21,7 +18,7 @@ class TracingFunctionHolder:
|
||||
'''
|
||||
_original_tracing = None
|
||||
_warn = True
|
||||
_lock = threading.Lock()
|
||||
_lock = _pydev_thread.allocate_lock()
|
||||
_traceback_limit = 1
|
||||
_warnings_shown = {}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from types import * #@UnusedWildImport
|
||||
|
||||
from pydevd_custom_frames import getCustomFrame
|
||||
from pydevd_xml import *
|
||||
from _pydev_imps import _pydev_thread
|
||||
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
@@ -15,11 +16,7 @@ except ImportError:
|
||||
from io import StringIO
|
||||
import sys #@Reimport
|
||||
|
||||
if USE_LIB_COPY:
|
||||
import _pydev_threading as threading
|
||||
else:
|
||||
import threading
|
||||
import pydevd_resolver
|
||||
import _pydev_threading as threading
|
||||
import traceback
|
||||
import pydevd_save_locals
|
||||
from pydev_imports import Exec, quote, execfile
|
||||
@@ -71,7 +68,7 @@ def dumpFrames(thread_id):
|
||||
# AdditionalFramesContainer
|
||||
#===============================================================================
|
||||
class AdditionalFramesContainer:
|
||||
lock = threading.Lock()
|
||||
lock = _pydev_thread.allocate_lock()
|
||||
additional_frames = {} #dict of dicts
|
||||
|
||||
|
||||
@@ -204,7 +201,7 @@ def getVariable(thread_id, frame_id, scope, attrs):
|
||||
attrList = []
|
||||
|
||||
if scope == 'EXPRESSION':
|
||||
for count in range(len(attrList)):
|
||||
for count in xrange(len(attrList)):
|
||||
if count == 0:
|
||||
# An Expression can be in any scope (globals/locals), therefore it needs to evaluated as an expression
|
||||
var = evaluateExpression(thread_id, frame_id, attrList[count], False)
|
||||
|
||||
@@ -75,7 +75,7 @@ def main():
|
||||
|
||||
if test_framework == 0:
|
||||
|
||||
pydev_runfiles.main(configuration)
|
||||
return pydev_runfiles.main(configuration) #Note: still doesn't return a proper value.
|
||||
|
||||
else:
|
||||
#We'll convert the parameters to what nose or py.test expects.
|
||||
@@ -144,7 +144,8 @@ def main():
|
||||
import pydev_runfiles_nose
|
||||
PYDEV_NOSE_PLUGIN_SINGLETON = pydev_runfiles_nose.StartPydevNosePluginSingleton(configuration)
|
||||
argv.append('--with-pydevplugin')
|
||||
nose.run(argv=argv, addplugins=[PYDEV_NOSE_PLUGIN_SINGLETON])
|
||||
# Return 'not' because it will return 'success' (so, exit == 0 if success)
|
||||
return not nose.run(argv=argv, addplugins=[PYDEV_NOSE_PLUGIN_SINGLETON])
|
||||
|
||||
elif test_framework == PY_TEST_FRAMEWORK:
|
||||
if DEBUG:
|
||||
@@ -189,7 +190,7 @@ def main():
|
||||
|
||||
argv.append('-p')
|
||||
argv.append('pydev_runfiles_pytest2')
|
||||
pytest.main(argv)
|
||||
return pytest.main(argv)
|
||||
|
||||
else:
|
||||
raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))
|
||||
|
||||
@@ -3,6 +3,7 @@ import unittest
|
||||
|
||||
import pydevconsole
|
||||
from pydev_imports import xmlrpclib, SimpleXMLRPCServer
|
||||
import sys
|
||||
from pydev_localhost import get_localhost
|
||||
from pydev_ipython_console_011 import get_pydev_frontend
|
||||
|
||||
|
||||
@@ -1,22 +1,7 @@
|
||||
import os.path
|
||||
import sys
|
||||
import weakref
|
||||
import threading
|
||||
import time
|
||||
|
||||
IS_JYTHON = sys.platform.find('java') != -1
|
||||
|
||||
try:
|
||||
this_file_name = __file__
|
||||
except NameError:
|
||||
# stupid jython. plain old __file__ isnt working for some reason
|
||||
import test_runfiles #@UnresolvedImport - importing the module itself
|
||||
this_file_name = test_runfiles.__file__
|
||||
|
||||
|
||||
desired_runfiles_path = os.path.normpath(os.path.dirname(this_file_name) + "/..")
|
||||
sys.path.insert(0, desired_runfiles_path)
|
||||
|
||||
import unittest
|
||||
import pydevd_referrers
|
||||
from pydev_imports import StringIO
|
||||
|
||||
@@ -36,10 +36,15 @@ class Test(unittest.TestCase):
|
||||
unittest.TestCase.tearDown(self)
|
||||
|
||||
def testIt(self):
|
||||
if not IS_JYTHON:
|
||||
return
|
||||
dbg('ok')
|
||||
|
||||
def testMessage(self):
|
||||
if not IS_JYTHON:
|
||||
return
|
||||
t = jycompletionserver.T(0)
|
||||
t.exit_process_on_kill = False
|
||||
|
||||
l = []
|
||||
l.append(('Def', 'description' , 'args'))
|
||||
@@ -65,6 +70,8 @@ class Test(unittest.TestCase):
|
||||
|
||||
|
||||
def testCompletionSocketsAndMessages(self):
|
||||
if not IS_JYTHON:
|
||||
return
|
||||
dbg('testCompletionSocketsAndMessages')
|
||||
t, socket = self.createConnections()
|
||||
self.socket = socket
|
||||
@@ -121,6 +128,7 @@ class Test(unittest.TestCase):
|
||||
Creates the connections needed for testing.
|
||||
'''
|
||||
t = jycompletionserver.T(p1)
|
||||
t.exit_process_on_kill = False
|
||||
|
||||
t.start()
|
||||
|
||||
|
||||
@@ -4,17 +4,14 @@
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
#make it as if we were executing from the directory above this one (so that we can use pycompletionserver
|
||||
#without the need for it being in the pythonpath)
|
||||
sys.argv[0] = os.path.dirname(sys.argv[0])
|
||||
#twice the dirname to get the previous level from this file.
|
||||
sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
|
||||
|
||||
#this does not work (they must be in the system pythonpath)
|
||||
#sys.path.insert(1, r"D:\bin\eclipse321\plugins\org.junit_3.8.1\junit.jar" ) #some late loading jar tests
|
||||
#sys.path.insert(1, r"D:\bin\eclipse331_1\plugins\org.apache.ant_1.7.0.v200706080842\lib\ant.jar" ) #some late loading jar tests
|
||||
|
||||
IS_JYTHON = 0
|
||||
if sys.platform.find('java') != -1:
|
||||
IS_JYTHON = 1
|
||||
from _pydev_jy_imports_tipper import ismethod
|
||||
from _pydev_jy_imports_tipper import isclass
|
||||
from _pydev_jy_imports_tipper import dirObj
|
||||
@@ -236,22 +233,24 @@ class TestCompl(unittest.TestCase):
|
||||
assert isMet[1][0].basicAsStr() == "function:met2 args=['arg1', 'arg2'], varargs=vararg, kwargs=kwarg, docs:docmet2"
|
||||
assert not isclass(met2)
|
||||
|
||||
|
||||
if not IS_JYTHON:
|
||||
# Disable tests if not running under Jython
|
||||
class TestMod(unittest.TestCase):
|
||||
pass
|
||||
class TestCompl(TestMod):
|
||||
pass
|
||||
class TestSearch(TestMod):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.platform.find('java') != -1:
|
||||
#Only run if jython
|
||||
suite = unittest.makeSuite(TestCompl)
|
||||
suite2 = unittest.makeSuite(TestMod)
|
||||
suite3 = unittest.makeSuite(TestSearch)
|
||||
#Only run if jython
|
||||
suite = unittest.makeSuite(TestCompl)
|
||||
suite2 = unittest.makeSuite(TestMod)
|
||||
suite3 = unittest.makeSuite(TestSearch)
|
||||
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite2)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite3)
|
||||
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite2)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite3)
|
||||
|
||||
# suite.addTest(Test('testCase12'))
|
||||
# suite = unittest.TestSuite()
|
||||
# unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
|
||||
else:
|
||||
sys.stdout.write('Not running jython tests for non-java platform: %s' % sys.platform)
|
||||
|
||||
@@ -7,81 +7,87 @@ from pydev_imports import StringIO, SimpleXMLRPCServer
|
||||
from pydev_localhost import get_localhost
|
||||
from pydev_console_utils import StdIn
|
||||
import socket
|
||||
from pydev_ipython_console_011 import get_pydev_frontend
|
||||
import time
|
||||
|
||||
# make it as if we were executing from the directory above this one
|
||||
sys.argv[0] = os.path.dirname(sys.argv[0])
|
||||
# twice the dirname to get the previous level from this file.
|
||||
sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
|
||||
try:
|
||||
xrange
|
||||
except:
|
||||
xrange = range
|
||||
|
||||
# PyDevFrontEnd depends on singleton in IPython, so you
|
||||
# can't make multiple versions. So we reuse front_end for
|
||||
# all the tests
|
||||
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
|
||||
stdout = sys.stdout = StringIO()
|
||||
stderr = sys.stderr = StringIO()
|
||||
|
||||
from pydev_ipython_console_011 import PyDevFrontEnd
|
||||
s = socket.socket()
|
||||
s.bind(('', 0))
|
||||
client_port = s.getsockname()[1]
|
||||
s.close()
|
||||
front_end = PyDevFrontEnd(get_localhost(), client_port)
|
||||
|
||||
|
||||
def addExec(code, expected_more=False):
|
||||
more = front_end.addExec(code)
|
||||
eq_(expected_more, more)
|
||||
|
||||
class TestBase(unittest.TestCase):
|
||||
|
||||
|
||||
def setUp(self):
|
||||
front_end.input_splitter.reset()
|
||||
stdout.truncate(0)
|
||||
stdout.seek(0)
|
||||
stderr.truncate(0)
|
||||
stderr.seek(0)
|
||||
# PyDevFrontEnd depends on singleton in IPython, so you
|
||||
# can't make multiple versions. So we reuse self.front_end for
|
||||
# all the tests
|
||||
self.front_end = get_pydev_frontend(get_localhost(), 0)
|
||||
|
||||
from pydev_ipython.inputhook import set_return_control_callback
|
||||
set_return_control_callback(lambda:True)
|
||||
self.front_end.clearBuffer()
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def addExec(self, code, expected_more=False):
|
||||
more = self.front_end.addExec(code)
|
||||
eq_(expected_more, more)
|
||||
|
||||
def redirectStdout(self):
|
||||
from IPython.utils import io
|
||||
|
||||
self.original_stdout = sys.stdout
|
||||
sys.stdout = io.stdout = StringIO()
|
||||
|
||||
def restoreStdout(self):
|
||||
from IPython.utils import io
|
||||
io.stdout = sys.stdout = self.original_stdout
|
||||
|
||||
|
||||
class TestPyDevFrontEnd(TestBase):
|
||||
|
||||
def testAddExec_1(self):
|
||||
addExec('if True:', True)
|
||||
self.addExec('if True:', True)
|
||||
|
||||
def testAddExec_2(self):
|
||||
addExec('if True:\n testAddExec_a = 10\n', True)
|
||||
#Change: 'more' must now be controlled in the client side after the initial 'True' returned.
|
||||
self.addExec('if True:\n testAddExec_a = 10\n', False)
|
||||
assert 'testAddExec_a' in self.front_end.getNamespace()
|
||||
|
||||
def testAddExec_3(self):
|
||||
assert 'testAddExec_a' not in front_end.getNamespace()
|
||||
addExec('if True:\n testAddExec_a = 10\n\n')
|
||||
assert 'testAddExec_a' in front_end.getNamespace()
|
||||
eq_(front_end.getNamespace()['testAddExec_a'], 10)
|
||||
assert 'testAddExec_x' not in self.front_end.getNamespace()
|
||||
self.addExec('if True:\n testAddExec_x = 10\n\n')
|
||||
assert 'testAddExec_x' in self.front_end.getNamespace()
|
||||
eq_(self.front_end.getNamespace()['testAddExec_x'], 10)
|
||||
|
||||
def testGetNamespace(self):
|
||||
assert 'testGetNamespace_a' not in front_end.getNamespace()
|
||||
addExec('testGetNamespace_a = 10')
|
||||
assert 'testGetNamespace_a' in front_end.getNamespace()
|
||||
eq_(front_end.getNamespace()['testGetNamespace_a'], 10)
|
||||
assert 'testGetNamespace_a' not in self.front_end.getNamespace()
|
||||
self.addExec('testGetNamespace_a = 10')
|
||||
assert 'testGetNamespace_a' in self.front_end.getNamespace()
|
||||
eq_(self.front_end.getNamespace()['testGetNamespace_a'], 10)
|
||||
|
||||
def testComplete(self):
|
||||
unused_text, matches = front_end.complete('%')
|
||||
unused_text, matches = self.front_end.complete('%')
|
||||
assert len(matches) > 1, 'at least one magic should appear in completions'
|
||||
|
||||
def testCompleteDoesNotDoPythonMatches(self):
|
||||
# Test that IPython's completions do not do the things that
|
||||
# PyDev's completions will handle
|
||||
addExec('testComplete_a = 5')
|
||||
addExec('testComplete_b = 10')
|
||||
addExec('testComplete_c = 15')
|
||||
unused_text, matches = front_end.complete('testComplete_')
|
||||
self.addExec('testComplete_a = 5')
|
||||
self.addExec('testComplete_b = 10')
|
||||
self.addExec('testComplete_c = 15')
|
||||
unused_text, matches = self.front_end.complete('testComplete_')
|
||||
assert len(matches) == 0
|
||||
|
||||
def testGetCompletions_1(self):
|
||||
# Test the merged completions include the standard completions
|
||||
addExec('testComplete_a = 5')
|
||||
addExec('testComplete_b = 10')
|
||||
addExec('testComplete_c = 15')
|
||||
res = front_end.getCompletions('testComplete_', 'testComplete_')
|
||||
self.addExec('testComplete_a = 5')
|
||||
self.addExec('testComplete_b = 10')
|
||||
self.addExec('testComplete_c = 15')
|
||||
res = self.front_end.getCompletions('testComplete_', 'testComplete_')
|
||||
matches = [f[0] for f in res]
|
||||
assert len(matches) == 3
|
||||
eq_(set(['testComplete_a', 'testComplete_b', 'testComplete_c']), set(matches))
|
||||
@@ -90,60 +96,80 @@ class TestPyDevFrontEnd(TestBase):
|
||||
# Test that we get IPython completions in results
|
||||
# we do this by checking kw completion which PyDev does
|
||||
# not do by default
|
||||
addExec('def ccc(ABC=123): pass')
|
||||
res = front_end.getCompletions('ccc(', '')
|
||||
self.addExec('def ccc(ABC=123): pass')
|
||||
res = self.front_end.getCompletions('ccc(', '')
|
||||
matches = [f[0] for f in res]
|
||||
assert 'ABC=' in matches
|
||||
|
||||
def testGetCompletions_3(self):
|
||||
# Test that magics return IPYTHON magic as type
|
||||
res = front_end.getCompletions('%cd', '%cd')
|
||||
res = self.front_end.getCompletions('%cd', '%cd')
|
||||
assert len(res) == 1
|
||||
eq_(res[0][3], '12') # '12' == IToken.TYPE_IPYTHON_MAGIC
|
||||
assert len(res[0][1]) > 100, 'docstring for %cd should be a reasonably long string'
|
||||
|
||||
class TestRunningCode(TestBase):
|
||||
def testPrint(self):
|
||||
addExec('print("output")')
|
||||
eq_(stdout.getvalue(), 'output\n')
|
||||
self.redirectStdout()
|
||||
try:
|
||||
self.addExec('print("output")')
|
||||
eq_(sys.stdout.getvalue(), 'output\n')
|
||||
finally:
|
||||
self.restoreStdout()
|
||||
|
||||
def testQuestionMark_1(self):
|
||||
addExec('?')
|
||||
assert len(stdout.getvalue()) > 1000, 'IPython help should be pretty big'
|
||||
self.redirectStdout()
|
||||
try:
|
||||
self.addExec('?')
|
||||
assert len(sys.stdout.getvalue()) > 1000, 'IPython help should be pretty big'
|
||||
finally:
|
||||
self.restoreStdout()
|
||||
|
||||
def testQuestionMark_2(self):
|
||||
addExec('int?')
|
||||
assert stdout.getvalue().find('Convert') != -1
|
||||
self.redirectStdout()
|
||||
try:
|
||||
self.addExec('int?')
|
||||
assert sys.stdout.getvalue().find('Convert') != -1
|
||||
finally:
|
||||
self.restoreStdout()
|
||||
|
||||
|
||||
def testGui(self):
|
||||
from pydev_ipython.inputhook import get_inputhook, set_stdin_file
|
||||
set_stdin_file(sys.stdin)
|
||||
assert get_inputhook() is None
|
||||
addExec('%gui tk')
|
||||
# we can't test the GUI works here because we aren't connected to XML-RPC so
|
||||
# nowhere for hook to run
|
||||
assert get_inputhook() is not None
|
||||
addExec('%gui none')
|
||||
assert get_inputhook() is None
|
||||
try:
|
||||
import Tkinter
|
||||
except:
|
||||
return
|
||||
else:
|
||||
from pydev_ipython.inputhook import get_inputhook
|
||||
assert get_inputhook() is None
|
||||
self.addExec('%gui tk')
|
||||
# we can't test the GUI works here because we aren't connected to XML-RPC so
|
||||
# nowhere for hook to run
|
||||
assert get_inputhook() is not None
|
||||
self.addExec('%gui none')
|
||||
assert get_inputhook() is None
|
||||
|
||||
def testHistory(self):
|
||||
''' Make sure commands are added to IPython's history '''
|
||||
addExec('a=1')
|
||||
addExec('b=2')
|
||||
_ih = front_end.getNamespace()['_ih']
|
||||
eq_(_ih[-1], 'b=2')
|
||||
eq_(_ih[-2], 'a=1')
|
||||
|
||||
addExec('history')
|
||||
hist = stdout.getvalue().split('\n')
|
||||
eq_(hist[-1], '')
|
||||
eq_(hist[-2], 'history')
|
||||
eq_(hist[-3], 'b=2')
|
||||
eq_(hist[-4], 'a=1')
|
||||
self.redirectStdout()
|
||||
try:
|
||||
self.addExec('a=1')
|
||||
self.addExec('b=2')
|
||||
_ih = self.front_end.getNamespace()['_ih']
|
||||
eq_(_ih[-1], 'b=2')
|
||||
eq_(_ih[-2], 'a=1')
|
||||
|
||||
self.addExec('history')
|
||||
hist = sys.stdout.getvalue().split('\n')
|
||||
eq_(hist[-1], '')
|
||||
eq_(hist[-2], 'history')
|
||||
eq_(hist[-3], 'b=2')
|
||||
eq_(hist[-4], 'a=1')
|
||||
finally:
|
||||
self.restoreStdout()
|
||||
|
||||
def testEdit(self):
|
||||
''' Make sure we can issue an edit command '''
|
||||
''' Make sure we can issue an edit command'''
|
||||
called_RequestInput = [False]
|
||||
called_IPythonEditor = [False]
|
||||
def startClientThread(client_port):
|
||||
@@ -163,26 +189,47 @@ class TestRunningCode(TestBase):
|
||||
handle_request_input = HandleRequestInput()
|
||||
|
||||
import pydev_localhost
|
||||
client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False)
|
||||
self.client_server = client_server = SimpleXMLRPCServer(
|
||||
(pydev_localhost.get_localhost(), self.client_port), logRequests=False)
|
||||
client_server.register_function(handle_request_input.RequestInput)
|
||||
client_server.register_function(handle_request_input.IPythonEditor)
|
||||
client_server.serve_forever()
|
||||
|
||||
def shutdown(self):
|
||||
return
|
||||
self.client_server.shutdown()
|
||||
|
||||
client_thread = ClientThread(client_port)
|
||||
client_thread.setDaemon(True)
|
||||
client_thread.start()
|
||||
return client_thread
|
||||
|
||||
startClientThread(client_port)
|
||||
# PyDevFrontEnd depends on singleton in IPython, so you
|
||||
# can't make multiple versions. So we reuse self.front_end for
|
||||
# all the tests
|
||||
s = socket.socket()
|
||||
s.bind(('', 0))
|
||||
self.client_port = client_port = s.getsockname()[1]
|
||||
s.close()
|
||||
self.front_end = get_pydev_frontend(get_localhost(), client_port)
|
||||
|
||||
client_thread = startClientThread(self.client_port)
|
||||
orig_stdin = sys.stdin
|
||||
sys.stdin = StdIn(self, get_localhost(), client_port)
|
||||
sys.stdin = StdIn(self, get_localhost(), self.client_port)
|
||||
try:
|
||||
filename = 'made_up_file.py'
|
||||
addExec('%edit ' + filename)
|
||||
eq_(called_IPythonEditor[0], (os.path.abspath(filename), 0))
|
||||
self.addExec('%edit ' + filename)
|
||||
|
||||
for i in xrange(10):
|
||||
if called_IPythonEditor[0] == (os.path.abspath(filename), '0'):
|
||||
break
|
||||
time.sleep(.1)
|
||||
|
||||
eq_(called_IPythonEditor[0], (os.path.abspath(filename), '0'))
|
||||
assert called_RequestInput[0], "Make sure the 'wait' parameter has been respected"
|
||||
finally:
|
||||
sys.stdin = orig_stdin
|
||||
client_thread.shutdown()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import threading
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.argv[0] = os.path.dirname(sys.argv[0])
|
||||
sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
|
||||
import pydevconsole
|
||||
from pydev_imports import xmlrpclib, SimpleXMLRPCServer, StringIO
|
||||
|
||||
@@ -19,104 +15,112 @@ except NameError:
|
||||
#=======================================================================================================================
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
def testConsoleHello(self):
|
||||
self.original_stdout = sys.stdout
|
||||
sys.stdout = StringIO()
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
ret = sys.stdout #@UnusedVariable
|
||||
sys.stdout = self.original_stdout
|
||||
#print_ ret.getvalue() -- use to see test output
|
||||
|
||||
def testConsoleHello(self):
|
||||
client_port, _server_port = self.getFreeAddresses()
|
||||
client_thread = self.startClientThread(client_port) #@UnusedVariable
|
||||
import time
|
||||
time.sleep(.3) #let's give it some time to start the threads
|
||||
|
||||
import pydev_localhost
|
||||
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, server=None)
|
||||
|
||||
(result,) = interpreter.hello("Hello pydevconsole")
|
||||
self.assertEqual(result, "Hello eclipse")
|
||||
|
||||
try:
|
||||
client_port, _server_port = self.getFreeAddresses()
|
||||
client_thread = self.startClientThread(client_port) #@UnusedVariable
|
||||
import time
|
||||
time.sleep(.3) #let's give it some time to start the threads
|
||||
|
||||
import pydev_localhost
|
||||
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.currentThread())
|
||||
|
||||
(result,) = interpreter.hello("Hello pydevconsole")
|
||||
self.assertEqual(result, "Hello eclipse")
|
||||
finally:
|
||||
sys.stdout = self.original_stdout
|
||||
|
||||
|
||||
def testConsoleRequests(self):
|
||||
client_port, _server_port = self.getFreeAddresses()
|
||||
client_thread = self.startClientThread(client_port) #@UnusedVariable
|
||||
import time
|
||||
time.sleep(.3) #let's give it some time to start the threads
|
||||
|
||||
import pydev_localhost
|
||||
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, server=None)
|
||||
interpreter.addExec('class Foo:')
|
||||
interpreter.addExec(' CONSTANT=1')
|
||||
interpreter.addExec('')
|
||||
interpreter.addExec('foo=Foo()')
|
||||
interpreter.addExec('foo.__doc__=None')
|
||||
interpreter.addExec('val = %s()' % (raw_input_name,))
|
||||
interpreter.addExec('50')
|
||||
interpreter.addExec('print (val)')
|
||||
found = sys.stdout.getvalue().split()
|
||||
self.original_stdout = sys.stdout
|
||||
sys.stdout = StringIO()
|
||||
|
||||
try:
|
||||
self.assertEqual(['50', 'input_request'], found)
|
||||
except:
|
||||
self.assertEqual(['input_request'], found) #IPython
|
||||
|
||||
comps = interpreter.getCompletions('foo.', 'foo.')
|
||||
self.assert_(
|
||||
('CONSTANT', '', '', '3') in comps or ('CONSTANT', '', '', '4') in comps, \
|
||||
'Found: %s' % comps
|
||||
)
|
||||
|
||||
comps = interpreter.getCompletions('"".', '"".')
|
||||
self.assert_(
|
||||
('__add__', 'x.__add__(y) <==> x+y', '', '3') in comps or
|
||||
('__add__', '', '', '4') in comps or
|
||||
('__add__', 'x.__add__(y) <==> x+y\r\nx.__add__(y) <==> x+y', '()', '2') in comps or
|
||||
('__add__', 'x.\n__add__(y) <==> x+yx.\n__add__(y) <==> x+y', '()', '2'),
|
||||
'Did not find __add__ in : %s' % (comps,)
|
||||
)
|
||||
|
||||
|
||||
completions = interpreter.getCompletions('', '')
|
||||
for c in completions:
|
||||
if c[0] == 'AssertionError':
|
||||
break
|
||||
else:
|
||||
self.fail('Could not find AssertionError')
|
||||
|
||||
completions = interpreter.getCompletions('Assert', 'Assert')
|
||||
for c in completions:
|
||||
if c[0] == 'RuntimeError':
|
||||
self.fail('Did not expect to find RuntimeError there')
|
||||
|
||||
self.assert_(('__doc__', None, '', '3') not in interpreter.getCompletions('foo.CO', 'foo.'))
|
||||
|
||||
comps = interpreter.getCompletions('va', 'va')
|
||||
self.assert_(('val', '', '', '3') in comps or ('val', '', '', '4') in comps)
|
||||
|
||||
interpreter.addExec('s = "mystring"')
|
||||
|
||||
desc = interpreter.getDescription('val')
|
||||
self.assert_(desc.find('str(object) -> string') >= 0 or
|
||||
desc == "'input_request'" or
|
||||
desc.find('str(string[, encoding[, errors]]) -> str') >= 0 or
|
||||
desc.find('str(Char* value)') >= 0 or
|
||||
desc.find('str(value: Char*)') >= 0,
|
||||
'Could not find what was needed in %s' % desc)
|
||||
|
||||
desc = interpreter.getDescription('val.join')
|
||||
self.assert_(desc.find('S.join(sequence) -> string') >= 0 or
|
||||
desc.find('S.join(sequence) -> str') >= 0 or
|
||||
desc.find('S.join(iterable) -> string') >= 0 or
|
||||
desc == "<builtin method 'join'>" or
|
||||
desc == "<built-in method join of str object>" or
|
||||
desc.find('str join(str self, list sequence)') >= 0 or
|
||||
desc.find('S.join(iterable) -> str') >= 0 or
|
||||
desc.find('join(self: str, sequence: list) -> str') >= 0,
|
||||
"Could not recognize: %s" % (desc,))
|
||||
client_port, _server_port = self.getFreeAddresses()
|
||||
client_thread = self.startClientThread(client_port) #@UnusedVariable
|
||||
import time
|
||||
time.sleep(.3) #let's give it some time to start the threads
|
||||
|
||||
import pydev_localhost
|
||||
from pydev_console_utils import CodeFragment
|
||||
|
||||
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.currentThread())
|
||||
sys.stdout = StringIO()
|
||||
interpreter.addExec(CodeFragment('class Foo:'))
|
||||
interpreter.addExec(CodeFragment(' CONSTANT=1'))
|
||||
interpreter.addExec(CodeFragment(''))
|
||||
interpreter.addExec(CodeFragment('foo=Foo()'))
|
||||
interpreter.addExec(CodeFragment('foo.__doc__=None'))
|
||||
interpreter.addExec(CodeFragment('val = %s()' % (raw_input_name,)))
|
||||
interpreter.addExec(CodeFragment('50'))
|
||||
interpreter.addExec(CodeFragment('print (val)'))
|
||||
found = sys.stdout.getvalue().split()
|
||||
try:
|
||||
self.assertEqual(['50', 'input_request'], found)
|
||||
except:
|
||||
self.assertEqual(['input_request'], found) #IPython
|
||||
|
||||
comps = interpreter.getCompletions('foo.', 'foo.')
|
||||
self.assert_(
|
||||
('CONSTANT', '', '', '3') in comps or ('CONSTANT', '', '', '4') in comps, \
|
||||
'Found: %s' % comps
|
||||
)
|
||||
|
||||
comps = interpreter.getCompletions('"".', '"".')
|
||||
self.assert_(
|
||||
('__add__', 'x.__add__(y) <==> x+y', '', '3') in comps or
|
||||
('__add__', '', '', '4') in comps or
|
||||
('__add__', 'x.__add__(y) <==> x+y\r\nx.__add__(y) <==> x+y', '()', '2') in comps or
|
||||
('__add__', 'x.\n__add__(y) <==> x+yx.\n__add__(y) <==> x+y', '()', '2'),
|
||||
'Did not find __add__ in : %s' % (comps,)
|
||||
)
|
||||
|
||||
|
||||
completions = interpreter.getCompletions('', '')
|
||||
for c in completions:
|
||||
if c[0] == 'AssertionError':
|
||||
break
|
||||
else:
|
||||
self.fail('Could not find AssertionError')
|
||||
|
||||
completions = interpreter.getCompletions('Assert', 'Assert')
|
||||
for c in completions:
|
||||
if c[0] == 'RuntimeError':
|
||||
self.fail('Did not expect to find RuntimeError there')
|
||||
|
||||
self.assert_(('__doc__', None, '', '3') not in interpreter.getCompletions('foo.CO', 'foo.'))
|
||||
|
||||
comps = interpreter.getCompletions('va', 'va')
|
||||
self.assert_(('val', '', '', '3') in comps or ('val', '', '', '4') in comps)
|
||||
|
||||
interpreter.addExec(CodeFragment('s = "mystring"'))
|
||||
|
||||
desc = interpreter.getDescription('val')
|
||||
self.assert_(desc.find('str(object) -> string') >= 0 or
|
||||
desc == "'input_request'" or
|
||||
desc.find('str(string[, encoding[, errors]]) -> str') >= 0 or
|
||||
desc.find('str(Char* value)') >= 0 or
|
||||
desc.find('str(object=\'\') -> string') >= 0 or
|
||||
desc.find('str(value: Char*)') >= 0 or
|
||||
desc.find('str(object=\'\') -> str') >= 0
|
||||
,
|
||||
'Could not find what was needed in %s' % desc)
|
||||
|
||||
desc = interpreter.getDescription('val.join')
|
||||
self.assert_(desc.find('S.join(sequence) -> string') >= 0 or
|
||||
desc.find('S.join(sequence) -> str') >= 0 or
|
||||
desc.find('S.join(iterable) -> string') >= 0 or
|
||||
desc == "<builtin method 'join'>" or
|
||||
desc == "<built-in method join of str object>" or
|
||||
desc.find('str join(str self, list sequence)') >= 0 or
|
||||
desc.find('S.join(iterable) -> str') >= 0 or
|
||||
desc.find('join(self: str, sequence: list) -> str') >= 0,
|
||||
"Could not recognize: %s" % (desc,))
|
||||
finally:
|
||||
sys.stdout = self.original_stdout
|
||||
|
||||
|
||||
def startClientThread(self, client_port):
|
||||
@@ -124,19 +128,28 @@ class Test(unittest.TestCase):
|
||||
def __init__(self, client_port):
|
||||
threading.Thread.__init__(self)
|
||||
self.client_port = client_port
|
||||
|
||||
def run(self):
|
||||
class HandleRequestInput:
|
||||
def RequestInput(self):
|
||||
client_thread.requested_input = True
|
||||
return 'input_request'
|
||||
|
||||
|
||||
def NotifyFinished(self, *args, **kwargs):
|
||||
client_thread.notified_finished += 1
|
||||
return 1
|
||||
|
||||
handle_request_input = HandleRequestInput()
|
||||
|
||||
|
||||
import pydev_localhost
|
||||
client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False)
|
||||
client_server.register_function(handle_request_input.RequestInput)
|
||||
client_server.register_function(handle_request_input.NotifyFinished)
|
||||
client_server.serve_forever()
|
||||
|
||||
|
||||
client_thread = ClientThread(client_port)
|
||||
client_thread.requested_input = False
|
||||
client_thread.notified_finished = 0
|
||||
client_thread.setDaemon(True)
|
||||
client_thread.start()
|
||||
return client_thread
|
||||
@@ -194,34 +207,50 @@ class Test(unittest.TestCase):
|
||||
|
||||
|
||||
def testServer(self):
|
||||
client_port, server_port = self.getFreeAddresses()
|
||||
class ServerThread(threading.Thread):
|
||||
def __init__(self, client_port, server_port):
|
||||
threading.Thread.__init__(self)
|
||||
self.client_port = client_port
|
||||
self.server_port = server_port
|
||||
|
||||
def run(self):
|
||||
import pydev_localhost
|
||||
pydevconsole.StartServer(pydev_localhost.get_localhost(), self.server_port, self.client_port)
|
||||
server_thread = ServerThread(client_port, server_port)
|
||||
server_thread.setDaemon(True)
|
||||
server_thread.start()
|
||||
|
||||
client_thread = self.startClientThread(client_port) #@UnusedVariable
|
||||
|
||||
import time
|
||||
time.sleep(.3) #let's give it some time to start the threads
|
||||
|
||||
import pydev_localhost
|
||||
server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port))
|
||||
server.addExec('class Foo:')
|
||||
server.addExec(' pass')
|
||||
server.addExec('')
|
||||
server.addExec('foo = Foo()')
|
||||
server.addExec('a = %s()' % (raw_input_name,))
|
||||
server.addExec('print (a)')
|
||||
self.assertEqual(['input_request'], sys.stdout.getvalue().split())
|
||||
self.original_stdout = sys.stdout
|
||||
sys.stdout = StringIO()
|
||||
try:
|
||||
client_port, server_port = self.getFreeAddresses()
|
||||
class ServerThread(threading.Thread):
|
||||
def __init__(self, client_port, server_port):
|
||||
threading.Thread.__init__(self)
|
||||
self.client_port = client_port
|
||||
self.server_port = server_port
|
||||
|
||||
def run(self):
|
||||
import pydev_localhost
|
||||
pydevconsole.StartServer(pydev_localhost.get_localhost(), self.server_port, self.client_port)
|
||||
server_thread = ServerThread(client_port, server_port)
|
||||
server_thread.setDaemon(True)
|
||||
server_thread.start()
|
||||
|
||||
client_thread = self.startClientThread(client_port) #@UnusedVariable
|
||||
|
||||
import time
|
||||
time.sleep(.3) #let's give it some time to start the threads
|
||||
sys.stdout = StringIO()
|
||||
|
||||
import pydev_localhost
|
||||
server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port))
|
||||
server.execLine('class Foo:')
|
||||
server.execLine(' pass')
|
||||
server.execLine('')
|
||||
server.execLine('foo = Foo()')
|
||||
server.execLine('a = %s()' % (raw_input_name,))
|
||||
server.execLine('print (a)')
|
||||
initial = time.time()
|
||||
while not client_thread.requested_input:
|
||||
if time.time() - initial > 2:
|
||||
raise AssertionError('Did not get the return asked before the timeout.')
|
||||
time.sleep(.1)
|
||||
|
||||
while ['input_request'] != sys.stdout.getvalue().split():
|
||||
if time.time() - initial > 2:
|
||||
break
|
||||
time.sleep(.1)
|
||||
self.assertEqual(['input_request'], sys.stdout.getvalue().split())
|
||||
finally:
|
||||
sys.stdout = self.original_stdout
|
||||
|
||||
#=======================================================================================================================
|
||||
# main
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
from _pydev_imps._pydev_thread import start_new_thread
|
||||
|
||||
#make it as if we were executing from the directory above this one (so that we can use pycompletionserver
|
||||
#without the need for it being in the pythonpath)
|
||||
@@ -13,6 +14,13 @@ sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
|
||||
IS_PYTHON_3K = 0
|
||||
if sys.platform.find('java') == -1:
|
||||
|
||||
try:
|
||||
import __builtin__ #@UnusedImport
|
||||
BUILTIN_MOD = '__builtin__'
|
||||
except ImportError:
|
||||
BUILTIN_MOD = 'builtins'
|
||||
|
||||
|
||||
|
||||
try:
|
||||
import inspect
|
||||
@@ -41,7 +49,7 @@ if sys.platform.find('java') == -1:
|
||||
unittest.TestCase.tearDown(self)
|
||||
|
||||
def testMessage(self):
|
||||
t = pycompletionserver.T(0)
|
||||
t = pycompletionserver.CompletionServer(0)
|
||||
|
||||
l = []
|
||||
l.append(('Def', 'description' , 'args'))
|
||||
@@ -62,14 +70,14 @@ if sys.platform.find('java') == -1:
|
||||
'''
|
||||
Creates the connections needed for testing.
|
||||
'''
|
||||
t = pycompletionserver.T(p1)
|
||||
|
||||
t.start()
|
||||
|
||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server.bind((pycompletionserver.HOST, p1))
|
||||
server.listen(1) #socket to receive messages.
|
||||
|
||||
t = pycompletionserver.CompletionServer(p1)
|
||||
t.exit_process_on_kill = False
|
||||
start_new_thread(t.run, ())
|
||||
|
||||
s, addr = server.accept()
|
||||
|
||||
return t, s
|
||||
@@ -106,6 +114,8 @@ if sys.platform.find('java') == -1:
|
||||
#math is a builtin and because of that, it starts with None as a file
|
||||
start = '@@COMPLETIONS(None,(__doc__,'
|
||||
start_2 = '@@COMPLETIONS(None,(__name__,'
|
||||
if '/math.so,' in completions or '/math.cpython-33m.so,' in completions or '/math.cpython-34m.so,' in completions:
|
||||
return
|
||||
self.assert_(completions.startswith(start) or completions.startswith(start_2), '%s DOESNT START WITH %s' % (completions, (start, start_2)))
|
||||
|
||||
self.assert_('@@COMPLETIONS' in completions)
|
||||
@@ -113,7 +123,7 @@ if sys.platform.find('java') == -1:
|
||||
|
||||
|
||||
#now, test i
|
||||
msg = quote_plus('__builtin__.list')
|
||||
msg = quote_plus('%s.list' % BUILTIN_MOD)
|
||||
send(socket, "@@IMPORTS:%s\nEND@@" % msg)
|
||||
found = self.readMsg()
|
||||
self.assert_('sort' in found, 'Could not find sort in: %s' % (found,))
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
'''
|
||||
@author Fabio Zadrozny
|
||||
'''
|
||||
import os
|
||||
import sys
|
||||
#make it as if we were executing from the directory above this one (so that we can use pycompletionserver
|
||||
#without the need for it being in the pythonpath)
|
||||
#twice the dirname to get the previous level from this file.
|
||||
sys.path.insert(1, os.path.split(os.path.split(__file__)[0])[0])
|
||||
|
||||
try:
|
||||
import __builtin__ #@UnusedImport
|
||||
@@ -50,13 +45,14 @@ if sys.platform.find('java') == -1:
|
||||
pass
|
||||
|
||||
def testImports5(self):
|
||||
tip = _pydev_imports_tipper.GenerateTip('__builtin__.list')
|
||||
tip = _pydev_imports_tipper.GenerateTip('%s.list' % BUILTIN_MOD)
|
||||
s = self.assertIn('sort', tip)
|
||||
self.CheckArgs(
|
||||
s,
|
||||
'(cmp=None, key=None, reverse=False)',
|
||||
'(self, object cmp, object key, bool reverse)',
|
||||
'(self, cmp: object, key: object, reverse: bool)'
|
||||
'(self, cmp: object, key: object, reverse: bool)',
|
||||
'(key=None, reverse=False)',
|
||||
)
|
||||
|
||||
def testImports2a(self):
|
||||
@@ -64,14 +60,24 @@ if sys.platform.find('java') == -1:
|
||||
self.assertIn('__doc__', tips)
|
||||
|
||||
def testImports2b(self):
|
||||
tips = _pydev_imports_tipper.GenerateTip('%s' % BUILTIN_MOD)
|
||||
t = self.assertIn('file' , tips)
|
||||
self.assert_('->' in t[1].strip() or 'file' in t[1])
|
||||
try:
|
||||
file
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
tips = _pydev_imports_tipper.GenerateTip('%s' % BUILTIN_MOD)
|
||||
t = self.assertIn('file' , tips)
|
||||
self.assert_('->' in t[1].strip() or 'file' in t[1])
|
||||
|
||||
def testImports2c(self):
|
||||
tips = _pydev_imports_tipper.GenerateTip('%s.file' % BUILTIN_MOD)
|
||||
t = self.assertIn('readlines' , tips)
|
||||
self.assert_('->' in t[1] or 'sizehint' in t[1])
|
||||
try:
|
||||
file # file is not available on py 3
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
tips = _pydev_imports_tipper.GenerateTip('%s.file' % BUILTIN_MOD)
|
||||
t = self.assertIn('readlines' , tips)
|
||||
self.assert_('->' in t[1] or 'sizehint' in t[1])
|
||||
|
||||
def testImports(self):
|
||||
'''
|
||||
@@ -110,9 +116,9 @@ if sys.platform.find('java') == -1:
|
||||
self.assertIn('RuntimeError' , tip)
|
||||
self.assertIn('RuntimeWarning' , tip)
|
||||
|
||||
t = self.assertIn('cmp' , tip)
|
||||
|
||||
self.CheckArgs(t, '(x, y)', '(object x, object y)', '(x: object, y: object)') #args
|
||||
# Remove cmp as it's not available on py 3
|
||||
#t = self.assertIn('cmp' , tip)
|
||||
#self.CheckArgs(t, '(x, y)', '(object x, object y)', '(x: object, y: object)') #args
|
||||
|
||||
t = self.assertIn('isinstance' , tip)
|
||||
self.CheckArgs(t, '(object, class_or_type_or_tuple)', '(object o, type typeinfo)', '(o: object, typeinfo: type)') #args
|
||||
|
||||
@@ -9,42 +9,44 @@ To run this:
|
||||
4) run: gl.glClearColor(1,1,1,1)
|
||||
"""
|
||||
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
import OpenGL.GL as gl
|
||||
import OpenGL.GLUT as glut
|
||||
if __name__ == '__main__':
|
||||
|
||||
def close():
|
||||
glut.glutDestroyWindow(glut.glutGetWindow())
|
||||
|
||||
def display():
|
||||
gl.glClear (gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
|
||||
glut.glutSwapBuffers()
|
||||
|
||||
def resize(width,height):
|
||||
gl.glViewport(0, 0, width, height+4)
|
||||
gl.glMatrixMode(gl.GL_PROJECTION)
|
||||
gl.glLoadIdentity()
|
||||
gl.glOrtho(0, width, 0, height+4, -1, 1)
|
||||
gl.glMatrixMode(gl.GL_MODELVIEW)
|
||||
|
||||
if glut.glutGetWindow() > 0:
|
||||
interactive = True
|
||||
glut.glutInit(sys.argv)
|
||||
glut.glutInitDisplayMode(glut.GLUT_DOUBLE |
|
||||
glut.GLUT_RGBA |
|
||||
glut.GLUT_DEPTH)
|
||||
else:
|
||||
interactive = False
|
||||
|
||||
glut.glutCreateWindow('gui-glut')
|
||||
glut.glutDisplayFunc(display)
|
||||
glut.glutReshapeFunc(resize)
|
||||
# This is necessary on osx to be able to close the window
|
||||
# (else the close button is disabled)
|
||||
if sys.platform == 'darwin' and not bool(glut.HAVE_FREEGLUT):
|
||||
glut.glutWMCloseFunc(close)
|
||||
gl.glClearColor(0,0,0,1)
|
||||
|
||||
if not interactive:
|
||||
glut.glutMainLoop()
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
import OpenGL.GL as gl
|
||||
import OpenGL.GLUT as glut
|
||||
|
||||
def close():
|
||||
glut.glutDestroyWindow(glut.glutGetWindow())
|
||||
|
||||
def display():
|
||||
gl.glClear (gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
|
||||
glut.glutSwapBuffers()
|
||||
|
||||
def resize(width,height):
|
||||
gl.glViewport(0, 0, width, height+4)
|
||||
gl.glMatrixMode(gl.GL_PROJECTION)
|
||||
gl.glLoadIdentity()
|
||||
gl.glOrtho(0, width, 0, height+4, -1, 1)
|
||||
gl.glMatrixMode(gl.GL_MODELVIEW)
|
||||
|
||||
if glut.glutGetWindow() > 0:
|
||||
interactive = True
|
||||
glut.glutInit(sys.argv)
|
||||
glut.glutInitDisplayMode(glut.GLUT_DOUBLE |
|
||||
glut.GLUT_RGBA |
|
||||
glut.GLUT_DEPTH)
|
||||
else:
|
||||
interactive = False
|
||||
|
||||
glut.glutCreateWindow('gui-glut')
|
||||
glut.glutDisplayFunc(display)
|
||||
glut.glutReshapeFunc(resize)
|
||||
# This is necessary on osx to be able to close the window
|
||||
# (else the close button is disabled)
|
||||
if sys.platform == 'darwin' and not bool(glut.HAVE_FREEGLUT):
|
||||
glut.glutWMCloseFunc(close)
|
||||
gl.glClearColor(0,0,0,1)
|
||||
|
||||
if not interactive:
|
||||
glut.glutMainLoop()
|
||||
|
||||
@@ -8,27 +8,28 @@ To run this:
|
||||
interactive console
|
||||
"""
|
||||
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
|
||||
|
||||
def hello_world(wigdet, data=None):
|
||||
print("Hello World")
|
||||
|
||||
def delete_event(widget, event, data=None):
|
||||
return False
|
||||
|
||||
def destroy(widget, data=None):
|
||||
gtk.main_quit()
|
||||
|
||||
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
window.connect("delete_event", delete_event)
|
||||
window.connect("destroy", destroy)
|
||||
button = gtk.Button("Hello World")
|
||||
button.connect("clicked", hello_world, None)
|
||||
|
||||
window.add(button)
|
||||
button.show()
|
||||
window.show()
|
||||
|
||||
if __name__ == '__main__':
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
|
||||
|
||||
def hello_world(wigdet, data=None):
|
||||
print("Hello World")
|
||||
|
||||
def delete_event(widget, event, data=None):
|
||||
return False
|
||||
|
||||
def destroy(widget, data=None):
|
||||
gtk.main_quit()
|
||||
|
||||
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
window.connect("delete_event", delete_event)
|
||||
window.connect("destroy", destroy)
|
||||
button = gtk.Button("Hello World")
|
||||
button.connect("clicked", hello_world, None)
|
||||
|
||||
window.add(button)
|
||||
button.show()
|
||||
window.show()
|
||||
|
||||
|
||||
@@ -8,25 +8,26 @@ To run this:
|
||||
interactive console
|
||||
"""
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
def hello_world(wigdet, data=None):
|
||||
print("Hello World")
|
||||
|
||||
def delete_event(widget, event, data=None):
|
||||
return False
|
||||
|
||||
def destroy(widget, data=None):
|
||||
Gtk.main_quit()
|
||||
|
||||
window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
|
||||
window.connect("delete_event", delete_event)
|
||||
window.connect("destroy", destroy)
|
||||
button = Gtk.Button("Hello World")
|
||||
button.connect("clicked", hello_world, None)
|
||||
|
||||
window.add(button)
|
||||
button.show()
|
||||
window.show()
|
||||
|
||||
if __name__ == '__main__':
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
def hello_world(wigdet, data=None):
|
||||
print("Hello World")
|
||||
|
||||
def delete_event(widget, event, data=None):
|
||||
return False
|
||||
|
||||
def destroy(widget, data=None):
|
||||
Gtk.main_quit()
|
||||
|
||||
window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
|
||||
window.connect("delete_event", delete_event)
|
||||
window.connect("destroy", destroy)
|
||||
button = Gtk.Button("Hello World")
|
||||
button.connect("clicked", hello_world, None)
|
||||
|
||||
window.add(button)
|
||||
button.show()
|
||||
window.show()
|
||||
|
||||
|
||||
@@ -8,20 +8,21 @@ To run this:
|
||||
interactive console
|
||||
"""
|
||||
|
||||
import pyglet
|
||||
|
||||
|
||||
window = pyglet.window.Window()
|
||||
label = pyglet.text.Label('Hello, world',
|
||||
font_name='Times New Roman',
|
||||
font_size=36,
|
||||
x=window.width//2, y=window.height//2,
|
||||
anchor_x='center', anchor_y='center')
|
||||
@window.event
|
||||
def on_close():
|
||||
window.close()
|
||||
|
||||
@window.event
|
||||
def on_draw():
|
||||
window.clear()
|
||||
label.draw()
|
||||
if __name__ == '__main__':
|
||||
import pyglet
|
||||
|
||||
|
||||
window = pyglet.window.Window()
|
||||
label = pyglet.text.Label('Hello, world',
|
||||
font_name='Times New Roman',
|
||||
font_size=36,
|
||||
x=window.width//2, y=window.height//2,
|
||||
anchor_x='center', anchor_y='center')
|
||||
@window.event
|
||||
def on_close():
|
||||
window.close()
|
||||
|
||||
@window.event
|
||||
def on_draw():
|
||||
window.clear()
|
||||
label.draw()
|
||||
|
||||
@@ -10,26 +10,27 @@ To run this:
|
||||
Ref: Modified from http://zetcode.com/tutorials/pyqt4/firstprograms/
|
||||
"""
|
||||
|
||||
import sys
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
||||
class SimpleWindow(QtGui.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
QtGui.QWidget.__init__(self, parent)
|
||||
|
||||
self.setGeometry(300, 300, 200, 80)
|
||||
self.setWindowTitle('Hello World')
|
||||
|
||||
quit = QtGui.QPushButton('Close', self)
|
||||
quit.setGeometry(10, 10, 60, 35)
|
||||
|
||||
self.connect(quit, QtCore.SIGNAL('clicked()'),
|
||||
self, QtCore.SLOT('close()'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtCore.QCoreApplication.instance()
|
||||
if app is None:
|
||||
app = QtGui.QApplication([])
|
||||
|
||||
sw = SimpleWindow()
|
||||
sw.show()
|
||||
import sys
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
||||
class SimpleWindow(QtGui.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
QtGui.QWidget.__init__(self, parent)
|
||||
|
||||
self.setGeometry(300, 300, 200, 80)
|
||||
self.setWindowTitle('Hello World')
|
||||
|
||||
quit = QtGui.QPushButton('Close', self)
|
||||
quit.setGeometry(10, 10, 60, 35)
|
||||
|
||||
self.connect(quit, QtCore.SIGNAL('clicked()'),
|
||||
self, QtCore.SLOT('close()'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtCore.QCoreApplication.instance()
|
||||
if app is None:
|
||||
app = QtGui.QApplication([])
|
||||
|
||||
sw = SimpleWindow()
|
||||
sw.show()
|
||||
|
||||
@@ -8,24 +8,26 @@ To run this:
|
||||
interactive console
|
||||
"""
|
||||
|
||||
try:
|
||||
from Tkinter import *
|
||||
except:
|
||||
# Python 3
|
||||
from tkinter import *
|
||||
|
||||
class MyApp:
|
||||
|
||||
def __init__(self, root):
|
||||
frame = Frame(root)
|
||||
frame.pack()
|
||||
|
||||
self.button = Button(frame, text="Hello", command=self.hello_world)
|
||||
self.button.pack(side=LEFT)
|
||||
|
||||
def hello_world(self):
|
||||
print("Hello World!")
|
||||
|
||||
root = Tk()
|
||||
|
||||
app = MyApp(root)
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
from Tkinter import *
|
||||
except:
|
||||
# Python 3
|
||||
from tkinter import *
|
||||
|
||||
class MyApp:
|
||||
|
||||
def __init__(self, root):
|
||||
frame = Frame(root)
|
||||
frame.pack()
|
||||
|
||||
self.button = Button(frame, text="Hello", command=self.hello_world)
|
||||
self.button.pack(side=LEFT)
|
||||
|
||||
def hello_world(self):
|
||||
print("Hello World!")
|
||||
|
||||
root = Tk()
|
||||
|
||||
app = MyApp(root)
|
||||
|
||||
@@ -11,91 +11,93 @@ To run this:
|
||||
Ref: Modified from wxPython source code wxPython/samples/simple/simple.py
|
||||
"""
|
||||
|
||||
import wx
|
||||
|
||||
|
||||
class MyFrame(wx.Frame):
|
||||
"""
|
||||
This is MyFrame. It just shows a few controls on a wxPanel,
|
||||
and has a simple menu.
|
||||
"""
|
||||
def __init__(self, parent, title):
|
||||
wx.Frame.__init__(self, parent, -1, title,
|
||||
pos=(150, 150), size=(350, 200))
|
||||
|
||||
# Create the menubar
|
||||
menuBar = wx.MenuBar()
|
||||
|
||||
# and a menu
|
||||
menu = wx.Menu()
|
||||
|
||||
# add an item to the menu, using \tKeyName automatically
|
||||
# creates an accelerator, the third param is some help text
|
||||
# that will show up in the statusbar
|
||||
menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")
|
||||
|
||||
# bind the menu event to an event handler
|
||||
self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)
|
||||
|
||||
# and put the menu on the menubar
|
||||
menuBar.Append(menu, "&File")
|
||||
self.SetMenuBar(menuBar)
|
||||
|
||||
self.CreateStatusBar()
|
||||
|
||||
# Now create the Panel to put the other controls on.
|
||||
panel = wx.Panel(self)
|
||||
|
||||
# and a few controls
|
||||
text = wx.StaticText(panel, -1, "Hello World!")
|
||||
text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
|
||||
text.SetSize(text.GetBestSize())
|
||||
btn = wx.Button(panel, -1, "Close")
|
||||
funbtn = wx.Button(panel, -1, "Just for fun...")
|
||||
|
||||
# bind the button events to handlers
|
||||
self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn)
|
||||
|
||||
# Use a sizer to layout the controls, stacked vertically and with
|
||||
# a 10 pixel border around each
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(text, 0, wx.ALL, 10)
|
||||
sizer.Add(btn, 0, wx.ALL, 10)
|
||||
sizer.Add(funbtn, 0, wx.ALL, 10)
|
||||
panel.SetSizer(sizer)
|
||||
panel.Layout()
|
||||
|
||||
|
||||
def OnTimeToClose(self, evt):
|
||||
"""Event handler for the button click."""
|
||||
print("See ya later!")
|
||||
self.Close()
|
||||
|
||||
def OnFunButton(self, evt):
|
||||
"""Event handler for the button click."""
|
||||
print("Having fun yet?")
|
||||
|
||||
|
||||
class MyApp(wx.App):
|
||||
def OnInit(self):
|
||||
frame = MyFrame(None, "Simple wxPython App")
|
||||
self.SetTopWindow(frame)
|
||||
|
||||
print("Print statements go to this stdout window by default.")
|
||||
|
||||
frame.Show(True)
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
app = wx.GetApp()
|
||||
if app is None:
|
||||
app = MyApp(redirect=False, clearSigInt=False)
|
||||
else:
|
||||
frame = MyFrame(None, "Simple wxPython App")
|
||||
app.SetTopWindow(frame)
|
||||
print("Print statements go to this stdout window by default.")
|
||||
frame.Show(True)
|
||||
|
||||
import wx
|
||||
|
||||
|
||||
class MyFrame(wx.Frame):
|
||||
"""
|
||||
This is MyFrame. It just shows a few controls on a wxPanel,
|
||||
and has a simple menu.
|
||||
"""
|
||||
def __init__(self, parent, title):
|
||||
wx.Frame.__init__(self, parent, -1, title,
|
||||
pos=(150, 150), size=(350, 200))
|
||||
|
||||
# Create the menubar
|
||||
menuBar = wx.MenuBar()
|
||||
|
||||
# and a menu
|
||||
menu = wx.Menu()
|
||||
|
||||
# add an item to the menu, using \tKeyName automatically
|
||||
# creates an accelerator, the third param is some help text
|
||||
# that will show up in the statusbar
|
||||
menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")
|
||||
|
||||
# bind the menu event to an event handler
|
||||
self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)
|
||||
|
||||
# and put the menu on the menubar
|
||||
menuBar.Append(menu, "&File")
|
||||
self.SetMenuBar(menuBar)
|
||||
|
||||
self.CreateStatusBar()
|
||||
|
||||
# Now create the Panel to put the other controls on.
|
||||
panel = wx.Panel(self)
|
||||
|
||||
# and a few controls
|
||||
text = wx.StaticText(panel, -1, "Hello World!")
|
||||
text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
|
||||
text.SetSize(text.GetBestSize())
|
||||
btn = wx.Button(panel, -1, "Close")
|
||||
funbtn = wx.Button(panel, -1, "Just for fun...")
|
||||
|
||||
# bind the button events to handlers
|
||||
self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn)
|
||||
|
||||
# Use a sizer to layout the controls, stacked vertically and with
|
||||
# a 10 pixel border around each
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(text, 0, wx.ALL, 10)
|
||||
sizer.Add(btn, 0, wx.ALL, 10)
|
||||
sizer.Add(funbtn, 0, wx.ALL, 10)
|
||||
panel.SetSizer(sizer)
|
||||
panel.Layout()
|
||||
|
||||
|
||||
def OnTimeToClose(self, evt):
|
||||
"""Event handler for the button click."""
|
||||
print("See ya later!")
|
||||
self.Close()
|
||||
|
||||
def OnFunButton(self, evt):
|
||||
"""Event handler for the button click."""
|
||||
print("Having fun yet?")
|
||||
|
||||
|
||||
class MyApp(wx.App):
|
||||
def OnInit(self):
|
||||
frame = MyFrame(None, "Simple wxPython App")
|
||||
self.SetTopWindow(frame)
|
||||
|
||||
print("Print statements go to this stdout window by default.")
|
||||
|
||||
frame.Show(True)
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
app = wx.GetApp()
|
||||
if app is None:
|
||||
app = MyApp(redirect=False, clearSigInt=False)
|
||||
else:
|
||||
frame = MyFrame(None, "Simple wxPython App")
|
||||
app.SetTopWindow(frame)
|
||||
print("Print statements go to this stdout window by default.")
|
||||
frame.Show(True)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ def m2(a):
|
||||
c = 30
|
||||
|
||||
def function2():
|
||||
print a
|
||||
print(a)
|
||||
|
||||
return a
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@ class A:
|
||||
|
||||
if __name__ == '__main__':
|
||||
a = A()
|
||||
print a._A__var
|
||||
print(a._A__var)
|
||||
# Evaluate 'a.__var' should give a._A__var_
|
||||
print('TEST SUCEEDED')
|
||||
|
||||
@@ -5,4 +5,4 @@ def Call():
|
||||
|
||||
if __name__ == '__main__':
|
||||
Call()
|
||||
print 'TEST SUCEEDED!'
|
||||
print('TEST SUCEEDED!')
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
def Method1():
|
||||
print 'm1'
|
||||
print('m1')
|
||||
|
||||
def Method2():
|
||||
print 'm2 before'
|
||||
print('m2 before')
|
||||
Method1()
|
||||
print 'm2 after'
|
||||
print('m2 after')
|
||||
|
||||
def Method3():
|
||||
print 'm3 before'
|
||||
print('m3 before')
|
||||
Method2()
|
||||
print 'm3 after'
|
||||
print('m3 after')
|
||||
|
||||
if __name__ == '__main__':
|
||||
Method3()
|
||||
print 'TEST SUCEEDED!'
|
||||
print('TEST SUCEEDED!')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
try:
|
||||
from PySide import QtCore
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
try:
|
||||
from PySide import QtCore
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
import sys
|
||||
import os
|
||||
import pydev_monkey
|
||||
sys.path.insert(0, os.path.split(os.path.split(__file__)[0])[0])
|
||||
|
||||
from pydevd_constants import Null
|
||||
import unittest
|
||||
|
||||
try:
|
||||
import thread
|
||||
except:
|
||||
import _thread as thread
|
||||
|
||||
try:
|
||||
xrange
|
||||
except:
|
||||
xrange = range
|
||||
|
||||
#=======================================================================================================================
|
||||
# TestCase
|
||||
#=======================================================================================================================
|
||||
@@ -40,10 +51,7 @@ class TestCase(unittest.TestCase):
|
||||
|
||||
|
||||
def testStartNewThread(self):
|
||||
import pydevd
|
||||
import thread
|
||||
original = thread.start_new_thread
|
||||
thread.start_new_thread = pydevd.pydev_start_new_thread
|
||||
pydev_monkey.patch_thread_modules()
|
||||
try:
|
||||
found = {}
|
||||
def function(a, b, *args, **kwargs):
|
||||
@@ -62,15 +70,11 @@ class TestCase(unittest.TestCase):
|
||||
|
||||
self.assertEqual({'a': 1, 'b': 2, 'args': (3, 4), 'kwargs': {'e': 2, 'd': 1}}, found)
|
||||
finally:
|
||||
thread.start_new_thread = original
|
||||
pydev_monkey.undo_patch_thread_modules()
|
||||
|
||||
|
||||
def testStartNewThread2(self):
|
||||
import pydevd
|
||||
import thread
|
||||
|
||||
original = thread.start_new_thread
|
||||
thread.start_new_thread = pydevd.pydev_start_new_thread
|
||||
pydev_monkey.patch_thread_modules()
|
||||
try:
|
||||
found = {}
|
||||
|
||||
@@ -101,7 +105,7 @@ class TestCase(unittest.TestCase):
|
||||
|
||||
self.assertEqual({'a': 1, 'b': 2, 'args': (3, 4), 'kwargs': {'e': 2, 'd': 1}}, found)
|
||||
finally:
|
||||
thread.start_new_thread = original
|
||||
pydev_monkey.undo_patch_thread_modules()
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,32 @@
|
||||
import unittest
|
||||
import pydev_monkey
|
||||
import sys
|
||||
from pydevd import SetupHolder
|
||||
from pydev_monkey import pydev_src_dir
|
||||
|
||||
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
|
||||
def test_monkey(self):
|
||||
check='''C:\\bin\\python.exe -u -c "
|
||||
original = SetupHolder.setup
|
||||
|
||||
try:
|
||||
SetupHolder.setup = {'client':'127.0.0.1', 'port': '0'}
|
||||
check='''C:\\bin\\python.exe -u -c "
|
||||
connect(\\"127.0.0.1\\")
|
||||
"'''
|
||||
sys.original_argv = []
|
||||
self.assertEqual('"-u" "-c" "\nconnect(\\"127.0.0.1\\")\n"', pydev_monkey.patch_arg_str_win(check))
|
||||
sys.original_argv = []
|
||||
self.assertEqual(
|
||||
'"C:\\bin\\python.exe" "-u" "-c" "import sys; '
|
||||
'sys.path.append(r\'%s\'); '
|
||||
'import pydevd; pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, '
|
||||
'trace_only_current_thread=False, patch_multiprocessing=True); '
|
||||
'\nconnect(\\"127.0.0.1\\")\n"' % pydev_src_dir,
|
||||
pydev_monkey.patch_arg_str_win(check)
|
||||
)
|
||||
finally:
|
||||
SetupHolder.setup = original
|
||||
|
||||
def test_str_to_args_windows(self):
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ def use_save_locals(name, value):
|
||||
save_locals(frame)
|
||||
|
||||
|
||||
def test_method(fn):
|
||||
def check_method(fn):
|
||||
"""
|
||||
A harness for testing methods that attempt to modify the values of locals on the stack.
|
||||
"""
|
||||
@@ -36,7 +36,7 @@ class TestSetLocals(unittest.TestCase):
|
||||
|
||||
|
||||
def test_set_locals_using_save_locals(self):
|
||||
x = test_method(use_save_locals)
|
||||
x = check_method(use_save_locals)
|
||||
self.assertEqual(x, 2) # Expected to succeed
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class TestSetLocals(unittest.TestCase):
|
||||
def check_co_vars(a):
|
||||
frame = sys._getframe()
|
||||
def function2():
|
||||
print a
|
||||
print(a)
|
||||
|
||||
assert 'a' in frame.f_code.co_cellvars
|
||||
frame = sys._getframe()
|
||||
|
||||
@@ -192,7 +192,7 @@ class RunfilesTest(unittest.TestCase):
|
||||
files_with_tests = [1 for t in self.all_tests if len(t._tests) > 0]
|
||||
self.assertNotEquals(len(self.files), len(files_with_tests))
|
||||
|
||||
def count_tests(self, tests):
|
||||
def count_suite(self, tests=None):
|
||||
total = 0
|
||||
for t in tests:
|
||||
total += t.countTestCases()
|
||||
@@ -208,60 +208,60 @@ class RunfilesTest(unittest.TestCase):
|
||||
|
||||
def test_finding_tests_from_modules_with_bad_filter_returns_0_tests(self):
|
||||
self._setup_scenario(self.file_dir, ["NO_TESTS_ARE_SURE_TO_HAVE_THIS_NAME"])
|
||||
self.assertEquals(0, self.count_tests(self.all_tests))
|
||||
self.assertEquals(0, self.count_suite(self.all_tests))
|
||||
|
||||
def test_finding_test_with_unique_name_returns_1_test(self):
|
||||
self._setup_scenario(self.file_dir, include_tests=["test_i_am_a_unique_test_name"])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEquals(1, self.count_tests(filtered_tests))
|
||||
self.assertEquals(1, self.count_suite(filtered_tests))
|
||||
|
||||
def test_finding_test_with_non_unique_name(self):
|
||||
self._setup_scenario(self.file_dir, include_tests=["test_non_unique_name"])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEquals(1, self.count_tests(filtered_tests) > 2)
|
||||
self.assertEquals(1, self.count_suite(filtered_tests) > 2)
|
||||
|
||||
def test_finding_tests_with_regex_filters(self):
|
||||
self._setup_scenario(self.file_dir, include_tests=["test_non*"])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEquals(1, self.count_tests(filtered_tests) > 2)
|
||||
self.assertEquals(1, self.count_suite(filtered_tests) > 2)
|
||||
|
||||
self._setup_scenario(self.file_dir, ["^$"])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEquals(0, self.count_tests(filtered_tests))
|
||||
self.assertEquals(0, self.count_suite(filtered_tests))
|
||||
|
||||
self._setup_scenario(self.file_dir, None, exclude_tests=["*"])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEquals(0, self.count_tests(filtered_tests))
|
||||
self.assertEquals(0, self.count_suite(filtered_tests))
|
||||
|
||||
def test_matching_tests(self):
|
||||
self._setup_scenario(self.file_dir, None, ['StillYetAnotherSampleTest'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(1, self.count_tests(filtered_tests))
|
||||
self.assertEqual(1, self.count_suite(filtered_tests))
|
||||
|
||||
self._setup_scenario(self.file_dir, None, ['SampleTest.test_xxxxxx1'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(1, self.count_tests(filtered_tests))
|
||||
self.assertEqual(1, self.count_suite(filtered_tests))
|
||||
|
||||
self._setup_scenario(self.file_dir, None, ['SampleTest'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(8, self.count_tests(filtered_tests))
|
||||
self.assertEqual(8, self.count_suite(filtered_tests))
|
||||
|
||||
self._setup_scenario(self.file_dir, None, ['AnotherSampleTest.todo_not_tested'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(1, self.count_tests(filtered_tests))
|
||||
self.assertEqual(1, self.count_suite(filtered_tests))
|
||||
|
||||
self._setup_scenario(self.file_dir, None, ['StillYetAnotherSampleTest', 'SampleTest.test_xxxxxx1'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(2, self.count_tests(filtered_tests))
|
||||
self.assertEqual(2, self.count_suite(filtered_tests))
|
||||
|
||||
self._setup_scenario(self.file_dir, None, exclude_tests=['*'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(self.count_tests(filtered_tests), 0)
|
||||
self.assertEqual(self.count_suite(filtered_tests), 0)
|
||||
|
||||
|
||||
self._setup_scenario(self.file_dir, None, exclude_tests=['*a*'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(self.count_tests(filtered_tests), 6)
|
||||
self.assertEqual(self.count_suite(filtered_tests), 6)
|
||||
|
||||
self.assertEqual(
|
||||
set(self.MyTestRunner.list_test_names(filtered_tests)),
|
||||
@@ -270,7 +270,7 @@ class RunfilesTest(unittest.TestCase):
|
||||
|
||||
self._setup_scenario(self.file_dir, None, exclude_tests=['*a*', '*x*'])
|
||||
filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
|
||||
self.assertEqual(self.count_tests(filtered_tests), 2)
|
||||
self.assertEqual(self.count_suite(filtered_tests), 2)
|
||||
|
||||
self.assertEqual(
|
||||
set(self.MyTestRunner.list_test_names(filtered_tests)),
|
||||
@@ -363,17 +363,43 @@ class RunfilesTest(unittest.TestCase):
|
||||
('notifyTest', 'ok', '', '', simple_test, 'SampleTest.test_xxxxxx2'),
|
||||
('notifyTest', 'ok', '', '', simple_test2, 'YetAnotherSampleTest.test_abc'),
|
||||
]
|
||||
|
||||
if not IS_JYTHON:
|
||||
expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpClass.',
|
||||
simpleClass_test.replace('/', os.path.sep), 'samples.simpleClass_test.SetUpClassTest <setUpClass>'))
|
||||
expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpModule.',
|
||||
simpleModule_test.replace('/', os.path.sep), 'samples.simpleModule_test <setUpModule>'))
|
||||
if 'samples.simpleClass_test' in str(notifications):
|
||||
expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpClass.',
|
||||
simpleClass_test.replace('/', os.path.sep), 'samples.simpleClass_test.SetUpClassTest <setUpClass>'))
|
||||
expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpModule.',
|
||||
simpleModule_test.replace('/', os.path.sep), 'samples.simpleModule_test <setUpModule>'))
|
||||
else:
|
||||
expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpClass.',
|
||||
simpleClass_test.replace('/', os.path.sep), 'simpleClass_test.SetUpClassTest <setUpClass>'))
|
||||
expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpModule.',
|
||||
simpleModule_test.replace('/', os.path.sep), 'simpleModule_test <setUpModule>'))
|
||||
else:
|
||||
expected.append(('notifyTest', 'ok', '', '', simpleClass_test, 'SetUpClassTest.test_blank'))
|
||||
expected.append(('notifyTest', 'ok', '', '', simpleModule_test, 'SetUpModuleTest.test_blank'))
|
||||
|
||||
expected.append(('notifyTestRunFinished',))
|
||||
expected.sort()
|
||||
new_notifications = []
|
||||
for notification in expected:
|
||||
try:
|
||||
if len(notification) == 6:
|
||||
# Some are binary on Py3.
|
||||
new_notifications.append((
|
||||
notification[0],
|
||||
notification[1],
|
||||
notification[2].encode('latin1'),
|
||||
notification[3].encode('latin1'),
|
||||
notification[4],
|
||||
notification[5],
|
||||
))
|
||||
else:
|
||||
new_notifications.append(notification)
|
||||
except:
|
||||
raise
|
||||
expected = new_notifications
|
||||
|
||||
notifications.sort()
|
||||
self.assertEqual(
|
||||
expected,
|
||||
|
||||
Reference in New Issue
Block a user