DebugClients/Python3/DebugVariables.py

changeset 5169
74e000797a93
child 5171
f1e9eebd5469
equal deleted inserted replaced
5168:e4a11c02374a 5169:74e000797a93
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing classes and functions to dump variable contents.
8 """
9
10 #
11 # This code was inspired by pydevd.
12 #
13
14 MaxItemsToHandle = 300
15 TooLargeMessage = ("Too large to show contents. Max items to show: " +
16 str(MaxItemsToHandle))
17 TooLargeAttribute = "Too large to be handled."
18
19 ############################################################
20 ## Classes implementing resolvers for various compund types
21 ############################################################
22
23 class BaseResolver(object):
24 """
25 Base class of the resolver class tree.
26 """
27 def resolve(self, var, attribute):
28 """
29 Public method to get an attribute from a variable.
30
31 @param var variable to extract an attribute or value from
32 @type any
33 @param attribute name of the attribute to extract
34 @type str
35 @return value of the attribute
36 @rtype any
37 """
38 raise NotImplementedError
39
40 def getDictionary(self, var):
41 """
42 Public method to get the attributes of a variable as a dictionary.
43
44 @param var variable to be converted
45 @type any
46 @return dictionary containing the variable attributes
47 @rtype dict
48 """
49 raise NotImplementedError
50
51
52 class DefaultResolver(BaseResolver):
53 """
54 Class used to resolve the default way.
55 """
56 def resolve(self, var, attribute):
57 """
58 Public method to get an attribute from a variable.
59
60 @param var variable to extract an attribute or value from
61 @type any
62 @param attribute name of the attribute to extract
63 @type str
64 @return value of the attribute
65 @rtype any
66 """
67 return getattr(var, attribute)
68
69 def getDictionary(self, var):
70 """
71 Public method to get the attributes of a variable as a dictionary.
72
73 @param var variable to be converted
74 @type any
75 @return dictionary containing the variable attributes
76 @rtype dict
77 """
78 names = dir(var)
79 if not names and hasattr(var, "__members__"):
80 names = var.__members__
81
82 d = {}
83 for name in names:
84 try:
85 attribute = getattr(var, name)
86 d[name] = attribute
87 except Exception:
88 pass # if we can't get it, simply ignore it
89
90 return d
91
92
93 class DictResolver(BaseResolver):
94 """
95 Class used to resolve from a dictionary.
96 """
97 def resolve(self, var, attribute):
98 """
99 Public method to get an attribute from a variable.
100
101 @param var variable to extract an attribute or value from
102 @type dict
103 @param attribute name of the attribute to extract
104 @type str
105 @return value of the attribute
106 @rtype any
107 """
108 if attribute in ('__len__', TooLargeAttribute):
109 return None
110
111 if "(" not in attribute:
112 try:
113 ## if attribute[0] == "'" and attribute[-1] == "'":
114 ## attribute = attribute[1:-1]
115 return var[attribute]
116 except Exception:
117 return getattr(var, attribute)
118
119 expectedID = int(attribute.split("(")[-1][:-1])
120 for key, value in var.items():
121 if id(key) == expectedID:
122 return value
123
124 return None
125
126 def __keyToStr(self, key):
127 if isinstance(key, str):
128 return repr(key)
129 else:
130 return key
131
132 def getDictionary(self, var):
133 """
134 Public method to get the attributes of a variable as a dictionary.
135
136 @param var variable to be converted
137 @type any
138 @return dictionary containing the variable attributes
139 @rtype dict
140 """
141 d = {}
142 count = 0
143 for key, value in var.items():
144 count += 1
145 key = "{0} ({1})".format(self.__keyToStr(key), id(key))
146 d[key] = value
147 if count > MaxItemsToHandle:
148 d[TooLargeAttribute] = TooLargeMessage
149 break
150
151 d["__len__"] = len(var)
152
153 # in case it has additional fields
154 additionals = defaultResolver.getDictionary(var)
155 d.update(additionals)
156
157 return d
158
159
160 class ListResolver(BaseResolver):
161 """
162 Class used to resolve from a tuple or list.
163 """
164 def resolve(self, var, attribute):
165 """
166 Public method to get an attribute from a variable.
167
168 @param var variable to extract an attribute or value from
169 @type tuple or list
170 @param attribute name of the attribute to extract
171 @type str
172 @return value of the attribute
173 @rtype any
174 """
175 if attribute in ('__len__', TooLargeAttribute):
176 return None
177
178 try:
179 return var[int(attribute)]
180 except Exception:
181 return getattr(var, attribute)
182
183 def getDictionary(self, var):
184 """
185 Public method to get the attributes of a variable as a dictionary.
186
187 @param var variable to be converted
188 @type any
189 @return dictionary containing the variable attributes
190 @rtype dict
191 """
192 length = len(var)
193 d = {}
194 formatStr = "{0:0" + str(len(str(length))) + "d}"
195 count = 0
196 for value in var:
197 d[formatStr.format(count)] = value
198 count += 1
199 if count > MaxItemsToHandle:
200 d[TooLargeAttribute] = TooLargeMessage
201 break
202
203 d["__len__"] = length
204
205 # in case it has additional fields
206 additionals = defaultResolver.getDictionary(var)
207 d.update(additionals)
208
209 return d
210
211
212 defaultResolver = DefaultResolver()
213 dictResolver = DictResolver()
214 listResolver = ListResolver()
215
216 # TODO: add resolver for set and frozenset
217 # TODO: add resolver for numpy arrays
218 # TODO: add resolver for Django MultiValueDict
219 # TODO: add resolver for collections.deque
220
221 ############################################################
222 ## Methods to determine the type of a variable and the
223 ## resolver class to use
224 ############################################################
225
226 _TypeMap = None
227
228 def _initTypeMap():
229 """
230 Protected function to initialize the type map
231 """
232 global _TypeMap
233
234 _TypeMap = [
235 (type(None), None,),
236 (int, None),
237 (float, None),
238 (complex, None),
239 (str, None),
240 (tuple, listResolver),
241 (list, listResolver),
242 (dict, dictResolver),
243 ]
244
245 try:
246 _TypeMap.append((long, None)) # __IGNORE_WARNING__
247 except Exception:
248 pass # not available on all python versions
249
250 try:
251 _TypeMap.append((unicode, None)) # __IGNORE_WARNING__
252 except Exception:
253 pass # not available on all python versions
254
255
256 def getType(obj):
257 """
258 Public method to get the type information for an object.
259
260 @param obj object to get type information for
261 @type any
262 @return tuple containing the type, type name, type string and resolver
263 @rtype tuple of type, str, str, BaseResolver
264 """
265 typeObject = type(obj)
266 typeName = typeObject.__name__
267 typeStr = str(typeObject)[8:-2]
268
269 if typeStr.startswith(("PyQt5.", "PyQt4.")):
270 resolver = None
271 else:
272 if _TypeMap is None:
273 _initTypeMap()
274
275 for typeData in _TypeMap:
276 if isinstance(obj, typeData[0]):
277 resolver = typeData[1]
278 break
279 else:
280 resolver = defaultResolver
281
282 return typeObject, typeName, typeStr, resolver

eric ide

mercurial