summaryrefslogtreecommitdiff
path: root/python/helpers/pydev/pydevd_vars.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/helpers/pydev/pydevd_vars.py')
-rw-r--r--python/helpers/pydev/pydevd_vars.py174
1 files changed, 125 insertions, 49 deletions
diff --git a/python/helpers/pydev/pydevd_vars.py b/python/helpers/pydev/pydevd_vars.py
index de8c2415fcae..0cc45f73710f 100644
--- a/python/helpers/pydev/pydevd_vars.py
+++ b/python/helpers/pydev/pydevd_vars.py
@@ -3,7 +3,6 @@
"""
import pickle
from django_frame import DjangoTemplateFrame
-from pydevd_constants import * #@UnusedWildImport
from types import * #@UnusedWildImport
from pydevd_custom_frames import getCustomFrame
@@ -19,16 +18,15 @@ if USE_LIB_COPY:
import _pydev_threading as threading
else:
import threading
-import pydevd_resolver
import traceback
import pydevd_save_locals
-from pydev_imports import Exec, quote, execfile
+from pydev_imports import Exec, execfile
try:
import types
frame_type = types.FrameType
except:
- frame_type = None
+ frame_type = type(sys._getframe())
#-------------------------------------------------------------------------- defining true and false for earlier versions
@@ -37,25 +35,14 @@ try:
__setFalse = False
except:
import __builtin__
-
setattr(__builtin__, 'True', 1)
setattr(__builtin__, 'False', 0)
#------------------------------------------------------------------------------------------------------ class for errors
-class VariableError(RuntimeError): pass
-
-class FrameNotFoundError(RuntimeError): pass
-
-
-if USE_PSYCO_OPTIMIZATION:
- try:
- import psyco
+class VariableError(RuntimeError):pass
- varToXML = psyco.proxy(varToXML)
- except ImportError:
- if hasattr(sys, 'exc_clear'): #jython does not have it
- sys.exc_clear() #don't keep the traceback -- clients don't want to see it
+class FrameNotFoundError(RuntimeError):pass
def iterFrames(initialFrame):
'''NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)'''
@@ -166,50 +153,127 @@ def findFrame(thread_id, frame_id):
traceback.print_exc()
return None
-def resolveCompoundVariable(thread_id, frame_id, scope, attrs):
- """ returns the value of the compound variable as a dictionary"""
+def getVariable(thread_id, frame_id, scope, attrs):
+ """
+ returns the value of a variable
+
+ :scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME
+
+ BY_ID means we'll traverse the list of all objects alive to get the object.
+
+ :attrs: after reaching the proper scope, we have to get the attributes until we find
+ the proper location (i.e.: obj\tattr1\tattr2)
+
+ :note: when BY_ID is used, the frame_id is considered the id of the object to find and
+ not the frame (as we don't care about the frame in this case).
+ """
+ if scope == 'BY_ID':
+ if thread_id != GetThreadId(threading.currentThread()) :
+ raise VariableError("getVariable: must execute on same thread")
+
+ try:
+ import gc
+ objects = gc.get_objects()
+ except:
+ pass #Not all python variants have it.
+ else:
+ frame_id = int(frame_id)
+ for var in objects:
+ if id(var) == frame_id:
+ if attrs is not None:
+ attrList = attrs.split('\t')
+ for k in attrList:
+ _type, _typeName, resolver = getType(var)
+ var = resolver.resolve(var, k)
+
+ return var
+
+ #If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected).
+ sys.stderr.write('Unable to find object with id: %s\n' % (frame_id,))
+ return None
+
frame = findFrame(thread_id, frame_id)
if frame is None:
return {}
- attrList = attrs.split('\t')
-
- if scope == "GLOBAL":
- var = frame.f_globals
- del attrList[0] # globals are special, and they get a single dummy unused attribute
+ if attrs is not None:
+ attrList = attrs.split('\t')
else:
- var = frame.f_locals
- type, _typeName, resolver = getType(var)
- try:
- resolver.resolve(var, attrList[0])
- except:
+ attrList = []
+
+ if scope == 'EXPRESSION':
+ 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)
+ else:
+ _type, _typeName, resolver = getType(var)
+ var = resolver.resolve(var, attrList[count])
+ else:
+ if scope == "GLOBAL":
var = frame.f_globals
+ del attrList[0] # globals are special, and they get a single dummy unused attribute
+ else:
+ var = frame.f_locals
+
+ for k in attrList:
+ _type, _typeName, resolver = getType(var)
+ var = resolver.resolve(var, k)
+
+ return var
- for k in attrList:
- type, _typeName, resolver = getType(var)
- var = resolver.resolve(var, k)
+
+def resolveCompoundVariable(thread_id, frame_id, scope, attrs):
+ """ returns the value of the compound variable as a dictionary"""
+
+ var = getVariable(thread_id, frame_id, scope, attrs)
try:
- type, _typeName, resolver = getType(var)
+ _type, _typeName, resolver = getType(var)
return resolver.getDictionary(var)
except:
+ sys.stderr.write('Error evaluating: thread_id: %s\nframe_id: %s\nscope: %s\nattrs: %s\n' % (
+ thread_id, frame_id, scope, attrs,))
traceback.print_exc()
-
-
+
+
def resolveVar(var, attrs):
attrList = attrs.split('\t')
-
+
for k in attrList:
type, _typeName, resolver = getType(var)
-
+
var = resolver.resolve(var, k)
-
+
try:
type, _typeName, resolver = getType(var)
return resolver.getDictionary(var)
except:
traceback.print_exc()
-
+
+
+def customOperation(thread_id, frame_id, scope, attrs, style, code_or_file, operation_fn_name):
+ """
+ We'll execute the code_or_file and then search in the namespace the operation_fn_name to execute with the given var.
+
+ code_or_file: either some code (i.e.: from pprint import pprint) or a file to be executed.
+ operation_fn_name: the name of the operation to execute after the exec (i.e.: pprint)
+ """
+ expressionValue = getVariable(thread_id, frame_id, scope, attrs)
+
+ try:
+ namespace = {'__name__': '<customOperation>'}
+ if style == "EXECFILE":
+ namespace['__file__'] = code_or_file
+ execfile(code_or_file, namespace, namespace)
+ else: # style == EXEC
+ namespace['__file__'] = '<customOperationCode>'
+ Exec(code_or_file, namespace, namespace)
+
+ return str(namespace[operation_fn_name](expressionValue))
+ except:
+ traceback.print_exc()
+
def evaluateExpression(thread_id, frame_id, expression, doExec):
'''returns the result of the evaluated expression
@@ -230,6 +294,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
try:
+
if doExec:
try:
#try to make it an eval (if it is an eval we can print it, otherwise we'll exec it and
@@ -240,7 +305,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
pydevd_save_locals.save_locals(frame)
else:
result = eval(compiled, updated_globals, frame.f_locals)
- if result is not None: #Only print if it's not None (as python does)
+ if result is not None: #Only print if it's not None (as python does)
sys.stdout.write('%s\n' % (result,))
return
@@ -251,7 +316,6 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
except Exception:
s = StringIO()
traceback.print_exc(file=s)
-
result = s.getvalue()
try:
@@ -265,6 +329,22 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
result = ExceptionOnEvaluate(result)
+ # Ok, we have the initial error message, but let's see if we're dealing with a name mangling error...
+ try:
+ if '__' in expression:
+ # Try to handle '__' name mangling...
+ split = expression.split('.')
+ curr = frame.f_locals.get(split[0])
+ for entry in split[1:]:
+ if entry.startswith('__') and not hasattr(curr, entry):
+ entry = '_%s%s' % (curr.__class__.__name__, entry)
+ curr = getattr(curr, entry)
+
+ result = curr
+ except:
+ pass
+
+
return result
finally:
#Should not be kept alive if an exception happens and this frame is kept in the stack.
@@ -273,22 +353,18 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
def changeAttrExpression(thread_id, frame_id, attr, expression):
'''Changes some attribute in a given frame.
- @note: it will not (currently) work if we're not in the topmost frame (that's a python
- deficiency -- and it appears that there is no way of making it currently work --
- will probably need some change to the python internals)
'''
frame = findFrame(thread_id, frame_id)
if frame is None:
return
- if isinstance(frame, DjangoTemplateFrame):
- result = eval(expression, frame.f_globals, frame.f_locals)
- frame.changeVariable(attr, result)
-
try:
expression = expression.replace('@LINE@', '\n')
-
+ if isinstance(frame, DjangoTemplateFrame):
+ result = eval(expression, frame.f_globals, frame.f_locals)
+ frame.changeVariable(attr, result)
+ return
if attr[:7] == "Globals":
attr = attr[8:]