Pydev.Debugger updated.

This commit is contained in:
Dmitry Trofimov
2014-08-26 15:24:03 +02:00
parent 02700775ac
commit ef377db337
64 changed files with 2030 additions and 2537 deletions
+7
View File
@@ -1,2 +1,9 @@
PyDev.Debugger
==============
[![Build Status](https://travis-ci.org/fabioz/PyDev.Debugger.png)](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).
+61 -57
View File
@@ -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
+11 -979
View File
@@ -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
+15 -14
View File
@@ -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))
+11 -8
View File
@@ -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)
+23 -17
View File
@@ -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 -4
View File
@@ -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))
+21 -32
View File
@@ -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()
+11 -44
View File
@@ -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)
+22 -10
View File
@@ -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
+5 -8
View File
@@ -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:
+118 -1
View File
@@ -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(
+9 -36
View File
@@ -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
View File
@@ -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
+2 -5
View File
@@ -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()
+67 -49
View File
@@ -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()
+28 -28
View File
@@ -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)
+24 -8
View File
@@ -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
+2 -1
View File
@@ -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).
+8 -9
View File
@@ -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)
+65 -32
View File
@@ -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
+11 -6
View File
@@ -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)))
+3 -2
View File
@@ -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!
+2 -5
View File
@@ -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 = {}
+4 -7
View File
@@ -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)
+4 -3
View File
@@ -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__':
+156 -127
View File
@@ -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
+16 -6
View File
@@ -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,))
+22 -16
View File
@@ -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
+40 -38
View File
@@ -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()
+25 -24
View File
@@ -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()
+23 -22
View File
@@ -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()
+23 -22
View File
@@ -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()
+23 -21
View File
@@ -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)
+88 -86
View File
@@ -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,