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