blob: 52bb186bc58ecd384147ce8265ef82d2508fb6c3 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001import pydev_log
2import traceback
3import pydevd_resolver
Tor Norbye1aa2e092014-08-20 17:01:23 -07004import sys
Tor Norbye3a2425a2013-11-04 10:16:08 -08005from pydevd_constants import * #@UnusedWildImport
Tor Norbyec667c1f2014-05-28 17:06:51 -07006
7from pydev_imports import quote
Tor Norbye3a2425a2013-11-04 10:16:08 -08008
9try:
Tor Norbyec667c1f2014-05-28 17:06:51 -070010 import types
11 frame_type = types.FrameType
Tor Norbye3a2425a2013-11-04 10:16:08 -080012except:
Tor Norbyec667c1f2014-05-28 17:06:51 -070013 frame_type = None
Tor Norbye3a2425a2013-11-04 10:16:08 -080014
15try:
16 from xml.sax.saxutils import escape
17
18 def makeValidXmlValue(s):
19 return escape(s, {'"': '"'})
20except:
21 #Simple replacement if it's not there.
22 def makeValidXmlValue(s):
23 return s.replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;')
24
25class ExceptionOnEvaluate:
26 def __init__(self, result):
27 self.result = result
28
29#------------------------------------------------------------------------------------------------------ resolvers in map
30
31if not sys.platform.startswith("java"):
32 typeMap = [
33 #None means that it should not be treated as a compound variable
34
35 #isintance does not accept a tuple on some versions of python, so, we must declare it expanded
36 (type(None), None,),
37 (int, None),
38 (float, None),
39 (complex, None),
40 (str, None),
41 (tuple, pydevd_resolver.tupleResolver),
42 (list, pydevd_resolver.tupleResolver),
43 (dict, pydevd_resolver.dictResolver),
44 ]
45
46 try:
47 typeMap.append((long, None))
48 except:
49 pass #not available on all python versions
50
51 try:
52 typeMap.append((unicode, None))
53 except:
54 pass #not available on all python versions
55
56 try:
57 typeMap.append((set, pydevd_resolver.setResolver))
58 except:
59 pass #not available on all python versions
60
61 try:
62 typeMap.append((frozenset, pydevd_resolver.setResolver))
63 except:
64 pass #not available on all python versions
65
Tor Norbyec667c1f2014-05-28 17:06:51 -070066 try:
67 import numpy
68 typeMap.append((numpy.ndarray, pydevd_resolver.ndarrayResolver))
69 except:
70 pass #numpy may not be installed
71
72 if frame_type is not None:
73 typeMap.append((frame_type, pydevd_resolver.frameResolver))
74
75
Tor Norbye3a2425a2013-11-04 10:16:08 -080076else: #platform is java
77 from org.python import core #@UnresolvedImport
Tor Norbye3a2425a2013-11-04 10:16:08 -080078 typeMap = [
79 (core.PyNone, None),
80 (core.PyInteger, None),
81 (core.PyLong, None),
82 (core.PyFloat, None),
83 (core.PyComplex, None),
84 (core.PyString, None),
85 (core.PyTuple, pydevd_resolver.tupleResolver),
86 (core.PyList, pydevd_resolver.tupleResolver),
87 (core.PyDictionary, pydevd_resolver.dictResolver),
88 (core.PyStringMap, pydevd_resolver.dictResolver),
89 ]
90
91 if hasattr(core, 'PyJavaInstance'):
92 #Jython 2.5b3 removed it.
93 typeMap.append((core.PyJavaInstance, pydevd_resolver.instanceResolver))
94
95
96def getType(o):
97 """ returns a triple (typeObject, typeString, resolver
98 resolver != None means that variable is a container,
99 and should be displayed as a hierarchy.
100 Use the resolver to get its attributes.
101
102 All container objects should have a resolver.
103 """
104
105 try:
106 type_object = type(o)
107 type_name = type_object.__name__
108 except:
109 #This happens for org.python.core.InitModule
110 return 'Unable to get Type', 'Unable to get Type', None
111
112 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700113
Tor Norbye3a2425a2013-11-04 10:16:08 -0800114 if type_name == 'org.python.core.PyJavaInstance':
Tor Norbyec667c1f2014-05-28 17:06:51 -0700115 return (type_object, type_name, pydevd_resolver.instanceResolver)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800116
117 if type_name == 'org.python.core.PyArray':
Tor Norbyec667c1f2014-05-28 17:06:51 -0700118 return (type_object, type_name, pydevd_resolver.jyArrayResolver)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800119
120 for t in typeMap:
121 if isinstance(o, t[0]):
Tor Norbyec667c1f2014-05-28 17:06:51 -0700122 return (type_object, type_name, t[1])
Tor Norbye3a2425a2013-11-04 10:16:08 -0800123 except:
124 traceback.print_exc()
125
126 #no match return default
Tor Norbyec667c1f2014-05-28 17:06:51 -0700127 return (type_object, type_name, pydevd_resolver.defaultResolver)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800128
129def frameVarsToXML(frame_f_locals):
130 """ dumps frame variables to XML
131 <var name="var_name" scope="local" type="type" value="value"/>
132 """
133 xml = ""
134
135 keys = frame_f_locals.keys()
136 if hasattr(keys, 'sort'):
137 keys.sort() #Python 3.0 does not have it
138 else:
139 keys = sorted(keys) #Jython 2.1 does not have it
140
141 for k in keys:
142 try:
143 v = frame_f_locals[k]
144 xml += varToXML(v, str(k))
145 except Exception:
146 traceback.print_exc()
147 pydev_log.error("Unexpected error, recovered safely.\n")
148
149 return xml
Tor Norbye1aa2e092014-08-20 17:01:23 -0700150
151
152def varToXML(val, name, doTrim=True, additionalInXml=''):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800153 """ single variable or dictionary to xml representation """
154
155 is_exception_on_eval = isinstance(val, ExceptionOnEvaluate)
156
157 if is_exception_on_eval:
158 v = val.result
159 else:
160 v = val
161
162 type, typeName, resolver = getType(v)
163
164 try:
165 if hasattr(v, '__class__'):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700166 if v.__class__ == frame_type:
167 value = pydevd_resolver.frameResolver.getFrameName(v)
168 else:
169 try:
170 cName = str(v.__class__)
171 if cName.find('.') != -1:
172 cName = cName.split('.')[-1]
Tor Norbye3a2425a2013-11-04 10:16:08 -0800173
Tor Norbye1aa2e092014-08-20 17:01:23 -0700174 elif cName.find("'") != -1: #does not have '.' (could be something like <type 'int'>)
175 cName = cName[cName.index("'") + 1:]
Tor Norbye3a2425a2013-11-04 10:16:08 -0800176
Tor Norbye1aa2e092014-08-20 17:01:23 -0700177 if cName.endswith("'>"):
178 cName = cName[:-2]
179 except:
180 cName = str(v.__class__)
181 value = '%s: %s' % (cName, v)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800182 else:
183 value = str(v)
184 except:
185 try:
186 value = repr(v)
187 except:
188 value = 'Unable to get repr for %s' % v.__class__
189
190 try:
191 name = quote(name, '/>_= ') #TODO: Fix PY-5834 without using quote
192 except:
193 pass
194 xml = '<var name="%s" type="%s"' % (makeValidXmlValue(name), makeValidXmlValue(typeName))
195
196 if value:
197 #cannot be too big... communication may not handle it.
198 if len(value) > MAXIMUM_VARIABLE_REPRESENTATION_SIZE and doTrim:
199 value = value[0:MAXIMUM_VARIABLE_REPRESENTATION_SIZE]
200 value += '...'
201
202 #fix to work with unicode values
203 try:
204 if not IS_PY3K:
205 if isinstance(value, unicode):
206 value = value.encode('utf-8')
207 else:
208 if isinstance(value, bytes):
209 value = value.encode('utf-8')
210 except TypeError: #in java, unicode is a function
211 pass
212
213 xmlValue = ' value="%s"' % (makeValidXmlValue(quote(value, '/>_= ')))
214 else:
215 xmlValue = ''
216
217 if is_exception_on_eval:
218 xmlCont = ' isErrorOnEval="True"'
219 else:
220 if resolver is not None:
221 xmlCont = ' isContainer="True"'
222 else:
223 xmlCont = ''
224
Tor Norbye1aa2e092014-08-20 17:01:23 -0700225 return ''.join((xml, xmlValue, xmlCont, additionalInXml, ' />\n'))
226
227if USE_PSYCO_OPTIMIZATION:
228 try:
229 import psyco
230
231 varToXML = psyco.proxy(varToXML)
232 except ImportError:
233 if hasattr(sys, 'exc_clear'): #jython does not have it
234 sys.exc_clear() #don't keep the traceback -- clients don't want to see it