| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 1 | """ pydevd_vars deals with variables: |
| 2 | resolution/conversion to XML. |
| 3 | """ |
| 4 | import pickle |
| 5 | from django_frame import DjangoTemplateFrame |
| Tor Norbye | c3d3a90 | 2014-09-04 13:24:04 -0700 | [diff] [blame^] | 6 | from pydevd_constants import * #@UnusedWildImport |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 7 | from types import * #@UnusedWildImport |
| 8 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 9 | from pydevd_custom_frames import getCustomFrame |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 10 | from pydevd_xml import * |
| Tor Norbye | c3d3a90 | 2014-09-04 13:24:04 -0700 | [diff] [blame^] | 11 | from _pydev_imps import _pydev_thread |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 12 | |
| 13 | try: |
| 14 | from StringIO import StringIO |
| 15 | except ImportError: |
| 16 | from io import StringIO |
| 17 | import sys #@Reimport |
| 18 | |
| Tor Norbye | c3d3a90 | 2014-09-04 13:24:04 -0700 | [diff] [blame^] | 19 | import _pydev_threading as threading |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 20 | import traceback |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 21 | import pydevd_save_locals |
| Tor Norbye | c3d3a90 | 2014-09-04 13:24:04 -0700 | [diff] [blame^] | 22 | from pydev_imports import Exec, quote, execfile |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 23 | |
| 24 | try: |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 25 | import types |
| 26 | frame_type = types.FrameType |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 27 | except: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 28 | frame_type = type(sys._getframe()) |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 29 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 30 | |
| 31 | #-------------------------------------------------------------------------- defining true and false for earlier versions |
| 32 | |
| 33 | try: |
| 34 | __setFalse = False |
| 35 | except: |
| 36 | import __builtin__ |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 37 | setattr(__builtin__, 'True', 1) |
| 38 | setattr(__builtin__, 'False', 0) |
| 39 | |
| 40 | #------------------------------------------------------------------------------------------------------ class for errors |
| 41 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 42 | class VariableError(RuntimeError):pass |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 43 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 44 | class FrameNotFoundError(RuntimeError):pass |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 45 | |
| 46 | def iterFrames(initialFrame): |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 47 | '''NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)''' |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 48 | #cannot use yield |
| 49 | frames = [] |
| 50 | |
| 51 | while initialFrame is not None: |
| 52 | frames.append(initialFrame) |
| 53 | initialFrame = initialFrame.f_back |
| 54 | |
| 55 | return frames |
| 56 | |
| 57 | def dumpFrames(thread_id): |
| 58 | sys.stdout.write('dumping frames\n') |
| 59 | if thread_id != GetThreadId(threading.currentThread()): |
| 60 | raise VariableError("findFrame: must execute on same thread") |
| 61 | |
| 62 | curFrame = GetFrame() |
| 63 | for frame in iterFrames(curFrame): |
| 64 | sys.stdout.write('%s\n' % pickle.dumps(frame)) |
| 65 | |
| 66 | |
| 67 | #=============================================================================== |
| 68 | # AdditionalFramesContainer |
| 69 | #=============================================================================== |
| 70 | class AdditionalFramesContainer: |
| Tor Norbye | c3d3a90 | 2014-09-04 13:24:04 -0700 | [diff] [blame^] | 71 | lock = _pydev_thread.allocate_lock() |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 72 | additional_frames = {} #dict of dicts |
| 73 | |
| 74 | |
| 75 | def addAdditionalFrameById(thread_id, frames_by_id): |
| 76 | AdditionalFramesContainer.additional_frames[thread_id] = frames_by_id |
| 77 | |
| 78 | |
| 79 | def removeAdditionalFrameById(thread_id): |
| 80 | del AdditionalFramesContainer.additional_frames[thread_id] |
| 81 | |
| 82 | |
| 83 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 84 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 85 | def findFrame(thread_id, frame_id): |
| 86 | """ returns a frame on the thread that has a given frame_id """ |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 87 | try: |
| 88 | curr_thread_id = GetThreadId(threading.currentThread()) |
| 89 | if thread_id != curr_thread_id : |
| 90 | try: |
| 91 | return getCustomFrame(thread_id, frame_id) #I.e.: thread_id could be a stackless frame id + thread_id. |
| 92 | except: |
| 93 | pass |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 94 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 95 | raise VariableError("findFrame: must execute on same thread (%s != %s)" % (thread_id, curr_thread_id)) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 96 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 97 | lookingFor = int(frame_id) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 98 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 99 | if AdditionalFramesContainer.additional_frames: |
| 100 | if DictContains(AdditionalFramesContainer.additional_frames, thread_id): |
| 101 | frame = AdditionalFramesContainer.additional_frames[thread_id].get(lookingFor) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 102 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 103 | if frame is not None: |
| 104 | return frame |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 105 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 106 | curFrame = GetFrame() |
| 107 | if frame_id == "*": |
| 108 | return curFrame # any frame is specified with "*" |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 109 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 110 | frameFound = None |
| 111 | |
| 112 | for frame in iterFrames(curFrame): |
| 113 | if lookingFor == id(frame): |
| 114 | frameFound = frame |
| 115 | del frame |
| 116 | break |
| 117 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 118 | del frame |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 119 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 120 | #Important: python can hold a reference to the frame from the current context |
| 121 | #if an exception is raised, so, if we don't explicitly add those deletes |
| 122 | #we might have those variables living much more than we'd want to. |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 123 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 124 | #I.e.: sys.exc_info holding reference to frame that raises exception (so, other places |
| 125 | #need to call sys.exc_clear()) |
| 126 | del curFrame |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 127 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 128 | if frameFound is None: |
| 129 | msgFrames = '' |
| 130 | i = 0 |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 131 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 132 | for frame in iterFrames(GetFrame()): |
| 133 | i += 1 |
| 134 | msgFrames += str(id(frame)) |
| 135 | if i % 5 == 0: |
| 136 | msgFrames += '\n' |
| 137 | else: |
| 138 | msgFrames += ' - ' |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 139 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 140 | errMsg = '''findFrame: frame not found. |
| 141 | Looking for thread_id:%s, frame_id:%s |
| 142 | Current thread_id:%s, available frames: |
| 143 | %s\n |
| 144 | ''' % (thread_id, lookingFor, curr_thread_id, msgFrames) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 145 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 146 | sys.stderr.write(errMsg) |
| 147 | return None |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 148 | |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 149 | return frameFound |
| 150 | except: |
| 151 | import traceback |
| 152 | traceback.print_exc() |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 153 | return None |
| 154 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 155 | def getVariable(thread_id, frame_id, scope, attrs): |
| 156 | """ |
| 157 | returns the value of a variable |
| 158 | |
| 159 | :scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME |
| 160 | |
| 161 | BY_ID means we'll traverse the list of all objects alive to get the object. |
| 162 | |
| 163 | :attrs: after reaching the proper scope, we have to get the attributes until we find |
| 164 | the proper location (i.e.: obj\tattr1\tattr2) |
| 165 | |
| 166 | :note: when BY_ID is used, the frame_id is considered the id of the object to find and |
| 167 | not the frame (as we don't care about the frame in this case). |
| 168 | """ |
| 169 | if scope == 'BY_ID': |
| 170 | if thread_id != GetThreadId(threading.currentThread()) : |
| 171 | raise VariableError("getVariable: must execute on same thread") |
| 172 | |
| 173 | try: |
| 174 | import gc |
| 175 | objects = gc.get_objects() |
| 176 | except: |
| 177 | pass #Not all python variants have it. |
| 178 | else: |
| 179 | frame_id = int(frame_id) |
| 180 | for var in objects: |
| 181 | if id(var) == frame_id: |
| 182 | if attrs is not None: |
| 183 | attrList = attrs.split('\t') |
| 184 | for k in attrList: |
| 185 | _type, _typeName, resolver = getType(var) |
| 186 | var = resolver.resolve(var, k) |
| 187 | |
| 188 | return var |
| 189 | |
| 190 | #If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected). |
| 191 | sys.stderr.write('Unable to find object with id: %s\n' % (frame_id,)) |
| 192 | return None |
| 193 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 194 | frame = findFrame(thread_id, frame_id) |
| 195 | if frame is None: |
| 196 | return {} |
| 197 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 198 | if attrs is not None: |
| 199 | attrList = attrs.split('\t') |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 200 | else: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 201 | attrList = [] |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 202 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 203 | if scope == 'EXPRESSION': |
| 204 | for count in xrange(len(attrList)): |
| 205 | if count == 0: |
| 206 | # An Expression can be in any scope (globals/locals), therefore it needs to evaluated as an expression |
| 207 | var = evaluateExpression(thread_id, frame_id, attrList[count], False) |
| 208 | else: |
| 209 | _type, _typeName, resolver = getType(var) |
| 210 | var = resolver.resolve(var, attrList[count]) |
| 211 | else: |
| 212 | if scope == "GLOBAL": |
| 213 | var = frame.f_globals |
| 214 | del attrList[0] # globals are special, and they get a single dummy unused attribute |
| 215 | else: |
| 216 | var = frame.f_locals |
| 217 | |
| 218 | for k in attrList: |
| 219 | _type, _typeName, resolver = getType(var) |
| 220 | var = resolver.resolve(var, k) |
| 221 | |
| 222 | return var |
| 223 | |
| 224 | |
| 225 | def resolveCompoundVariable(thread_id, frame_id, scope, attrs): |
| 226 | """ returns the value of the compound variable as a dictionary""" |
| 227 | |
| 228 | var = getVariable(thread_id, frame_id, scope, attrs) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 229 | |
| 230 | try: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 231 | _type, _typeName, resolver = getType(var) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 232 | return resolver.getDictionary(var) |
| 233 | except: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 234 | sys.stderr.write('Error evaluating: thread_id: %s\nframe_id: %s\nscope: %s\nattrs: %s\n' % ( |
| 235 | thread_id, frame_id, scope, attrs,)) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 236 | traceback.print_exc() |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 237 | |
| 238 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 239 | def resolveVar(var, attrs): |
| 240 | attrList = attrs.split('\t') |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 241 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 242 | for k in attrList: |
| 243 | type, _typeName, resolver = getType(var) |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 244 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 245 | var = resolver.resolve(var, k) |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 246 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 247 | try: |
| 248 | type, _typeName, resolver = getType(var) |
| 249 | return resolver.getDictionary(var) |
| 250 | except: |
| 251 | traceback.print_exc() |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 252 | |
| 253 | |
| 254 | def customOperation(thread_id, frame_id, scope, attrs, style, code_or_file, operation_fn_name): |
| 255 | """ |
| 256 | We'll execute the code_or_file and then search in the namespace the operation_fn_name to execute with the given var. |
| 257 | |
| 258 | code_or_file: either some code (i.e.: from pprint import pprint) or a file to be executed. |
| 259 | operation_fn_name: the name of the operation to execute after the exec (i.e.: pprint) |
| 260 | """ |
| 261 | expressionValue = getVariable(thread_id, frame_id, scope, attrs) |
| 262 | |
| 263 | try: |
| 264 | namespace = {'__name__': '<customOperation>'} |
| 265 | if style == "EXECFILE": |
| 266 | namespace['__file__'] = code_or_file |
| 267 | execfile(code_or_file, namespace, namespace) |
| 268 | else: # style == EXEC |
| 269 | namespace['__file__'] = '<customOperationCode>' |
| 270 | Exec(code_or_file, namespace, namespace) |
| 271 | |
| 272 | return str(namespace[operation_fn_name](expressionValue)) |
| 273 | except: |
| 274 | traceback.print_exc() |
| 275 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 276 | |
| 277 | def evaluateExpression(thread_id, frame_id, expression, doExec): |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 278 | '''returns the result of the evaluated expression |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 279 | @param doExec: determines if we should do an exec or an eval |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 280 | ''' |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 281 | frame = findFrame(thread_id, frame_id) |
| 282 | if frame is None: |
| 283 | return |
| 284 | |
| 285 | expression = str(expression.replace('@LINE@', '\n')) |
| 286 | |
| 287 | |
| 288 | #Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329 |
| 289 | #(Names not resolved in generator expression in method) |
| 290 | #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html |
| 291 | updated_globals = {} |
| 292 | updated_globals.update(frame.f_globals) |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 293 | updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 294 | |
| 295 | try: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 296 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 297 | if doExec: |
| 298 | try: |
| 299 | #try to make it an eval (if it is an eval we can print it, otherwise we'll exec it and |
| 300 | #it will have whatever the user actually did) |
| 301 | compiled = compile(expression, '<string>', 'eval') |
| 302 | except: |
| 303 | Exec(expression, updated_globals, frame.f_locals) |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 304 | pydevd_save_locals.save_locals(frame) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 305 | else: |
| 306 | result = eval(compiled, updated_globals, frame.f_locals) |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 307 | if result is not None: #Only print if it's not None (as python does) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 308 | sys.stdout.write('%s\n' % (result,)) |
| 309 | return |
| 310 | |
| 311 | else: |
| 312 | result = None |
| 313 | try: |
| 314 | result = eval(expression, updated_globals, frame.f_locals) |
| 315 | except Exception: |
| 316 | s = StringIO() |
| 317 | traceback.print_exc(file=s) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 318 | result = s.getvalue() |
| 319 | |
| 320 | try: |
| 321 | try: |
| 322 | etype, value, tb = sys.exc_info() |
| 323 | result = value |
| 324 | finally: |
| 325 | etype = value = tb = None |
| 326 | except: |
| 327 | pass |
| 328 | |
| 329 | result = ExceptionOnEvaluate(result) |
| 330 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 331 | # Ok, we have the initial error message, but let's see if we're dealing with a name mangling error... |
| 332 | try: |
| 333 | if '__' in expression: |
| 334 | # Try to handle '__' name mangling... |
| 335 | split = expression.split('.') |
| 336 | curr = frame.f_locals.get(split[0]) |
| 337 | for entry in split[1:]: |
| 338 | if entry.startswith('__') and not hasattr(curr, entry): |
| 339 | entry = '_%s%s' % (curr.__class__.__name__, entry) |
| 340 | curr = getattr(curr, entry) |
| 341 | |
| 342 | result = curr |
| 343 | except: |
| 344 | pass |
| 345 | |
| 346 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 347 | return result |
| 348 | finally: |
| 349 | #Should not be kept alive if an exception happens and this frame is kept in the stack. |
| 350 | del updated_globals |
| 351 | del frame |
| 352 | |
| 353 | def changeAttrExpression(thread_id, frame_id, attr, expression): |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 354 | '''Changes some attribute in a given frame. |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 355 | ''' |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 356 | frame = findFrame(thread_id, frame_id) |
| 357 | if frame is None: |
| 358 | return |
| 359 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 360 | try: |
| 361 | expression = expression.replace('@LINE@', '\n') |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 362 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 363 | if isinstance(frame, DjangoTemplateFrame): |
| 364 | result = eval(expression, frame.f_globals, frame.f_locals) |
| 365 | frame.changeVariable(attr, result) |
| 366 | return |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 367 | |
| 368 | if attr[:7] == "Globals": |
| 369 | attr = attr[8:] |
| 370 | if attr in frame.f_globals: |
| 371 | frame.f_globals[attr] = eval(expression, frame.f_globals, frame.f_locals) |
| 372 | return frame.f_globals[attr] |
| 373 | else: |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 374 | if pydevd_save_locals.is_save_locals_available(): |
| 375 | frame.f_locals[attr] = eval(expression, frame.f_globals, frame.f_locals) |
| 376 | pydevd_save_locals.save_locals(frame) |
| 377 | return |
| 378 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 379 | #default way (only works for changing it in the topmost frame) |
| 380 | result = eval(expression, frame.f_globals, frame.f_locals) |
| 381 | Exec('%s=%s' % (attr, expression), frame.f_globals, frame.f_locals) |
| 382 | return result |
| 383 | |
| 384 | |
| 385 | except Exception: |
| 386 | traceback.print_exc() |
| 387 | |
| 388 | |
| 389 | |
| 390 | |
| 391 | |