eric7/Debugger/VariablesViewer.py

branch
eric7
changeset 8568
890dfe038613
parent 8531
4ce885e452ac
child 8881
54e42bc2437a
equal deleted inserted replaced
8557:17fb004af51d 8568:890dfe038613
19 from PyQt6.QtWidgets import QTreeView, QAbstractItemView, QToolTip, QMenu 19 from PyQt6.QtWidgets import QTreeView, QAbstractItemView, QToolTip, QMenu
20 20
21 from EricWidgets.EricApplication import ericApp 21 from EricWidgets.EricApplication import ericApp
22 22
23 from .Config import ConfigVarTypeDispStrings 23 from .Config import ConfigVarTypeDispStrings
24 from DebugClients.Python.DebugConfig import ConfigQtNames, ConfigKnownQtTypes
25 24
26 import Preferences 25 import Preferences
27 import Utilities 26 import Utilities
28 27
29 SORT_ROLE = Qt.ItemDataRole.UserRole 28 SORT_ROLE = Qt.ItemDataRole.UserRole
31 30
32 class VariableItem: 31 class VariableItem:
33 """ 32 """
34 Class implementing the data structure for all variable items. 33 Class implementing the data structure for all variable items.
35 """ 34 """
36 Type2Indicators = {
37 # Python types
38 'list': '[]',
39 'tuple': '()',
40 'dict': '{:}', # __IGNORE_WARNING_M613__
41 'set': '{}', # __IGNORE_WARNING_M613__
42 'frozenset': '{}', # __IGNORE_WARNING_M613__
43 'numpy.ndarray': '[ndarray]', # __IGNORE_WARNING_M613__
44 }
45
46 # Initialize regular expression for unprintable strings 35 # Initialize regular expression for unprintable strings
47 rx_nonprintable = re.compile(r"""(\\x\d\d)+""") 36 rx_nonprintable = re.compile(r"""(\\x\d\d)+""")
48 37
49 noOfItemsStr = QCoreApplication.translate("VariablesViewer", "{0} items") 38 noOfItemsStr = QCoreApplication.translate("VariablesViewer", "{0} items")
50 unsized = QCoreApplication.translate("VariablesViewer", "unsized") 39 unsized = QCoreApplication.translate("VariablesViewer", "unsized")
51 40
52 arrayTypes = { 41 def __init__(self, parent, dvar, indicator, dtype, hasChildren, length,
53 'list', 'tuple', 'dict', 'set', 'frozenset', 'numpy.ndarray', 42 dvalue):
54 'django.MultiValueDict', 'array.array', 'collections.defaultdict',
55 "class 'dict_items'", "class 'dict_keys'", "class 'dict_values'",
56 }
57
58 nonExpandableTypes = (
59 'method_descriptor', 'wrapper_descriptor', '', 'getset_descriptor',
60 'method-wrapper', 'member_descriptor',
61 )
62
63 def __init__(self, parent, dvar, dtype, dvalue):
64 """ 43 """
65 Constructor 44 Constructor
66 45
67 @param parent reference to the parent item 46 @param parent reference to the parent item
68 @type VariableItem 47 @type VariableItem
69 @param dvar variable name 48 @param dvar variable name
70 @type str 49 @type str
50 @param indicator type indicator appended to the name
51 @type str
71 @param dtype type string 52 @param dtype type string
72 @type str 53 @type str
54 @param hasChildren indicator for children
55 @type bool
56 @param length length of the array or string (-1 if uninitialized
57 numpy.ndarray)
58 @type int
73 @param dvalue value string 59 @param dvalue value string
74 @type str 60 @type str
75 """ 61 """
76 self.parent = parent 62 self.parent = parent
77 # Take the additional methods into account for childCount 63 # Take the additional methods into account for childCount
78 self.methodCount = 0 64 self.methodCount = 0
79 self.childCount = 0 65 self.childCount = 0
80 self.currentCount = -1 # -1 indicates to (re)load children 66 self.currentCount = -1 # -1 indicates to (re)load children
81 # Indicator that there are children 67 # Indicator that there are children
82 self.hasChildren = False 68 self.hasChildren = hasChildren
83 self.populated = False 69 self.populated = False
84 # Indicator that item was at least once fully populated 70 # Indicator that item was at least once fully populated
85 self.wasPopulated = False 71 self.wasPopulated = False
86 72
87 self.children = [] 73 self.children = []
95 # Name including its ID if it's a dict, set, etc. 81 # Name including its ID if it's a dict, set, etc.
96 self.nameWithId = dvar 82 self.nameWithId = dvar
97 83
98 self.name = '' 84 self.name = ''
99 self.sort = '' 85 self.sort = ''
100 self.type = '' 86 vtype = ConfigVarTypeDispStrings.get(dtype, dtype)
101 self.indicator = '' 87 self.type = QCoreApplication.translate("VariablesViewer", vtype)
102 self.value = None 88 self.indicator = indicator
89 self.value = dvalue
103 self.valueShort = None 90 self.valueShort = None
104 self.tooltip = '' 91 self.tooltip = ''
105 92
106 self.__getName(dvar) 93 self.__getName(dvar)
107 self.__getType(dtype) 94 self.__getValue(dtype, dvalue, indicator, length)
108 self.__getValue(dtype, dvalue)
109 95
110 def __getName(self, dvar): 96 def __getName(self, dvar):
111 """ 97 """
112 Private method to extract the variable name. 98 Private method to extract the variable name.
113 99
124 pass 110 pass
125 111
126 self.name = dvar 112 self.name = dvar
127 try: 113 try:
128 # Convert numbers to strings with preceding zeros 114 # Convert numbers to strings with preceding zeros
129 sort = int(dvar) 115 asInt = int(dvar)
130 sort = "{0:06}".format(sort) 116 self.sort = "{0:06}".format(asInt)
131 except ValueError: 117 except ValueError:
132 sort = dvar.lower() 118 self.sort = dvar.lower()
133 119
134 self.sort = sort 120 def __getValue(self, dtype, dvalue, indicator, length):
135
136 def __getType(self, dtype):
137 """
138 Private method to process the type of the variable.
139
140 If type is known to have children, the corresponding flag is set.
141
142 @param dtype type string
143 @type str
144 """
145 # Python class?
146 if dtype.startswith('class '):
147 dtype = dtype[7:-1]
148 # Qt related stuff?
149 elif (
150 (dtype.startswith(ConfigQtNames) and
151 dtype.endswith(ConfigKnownQtTypes)) or
152 dtype in ('instance', 'class')
153 ):
154 self.hasChildren = True
155
156 # Special Qt types should not be expanded infinite
157 elif ".{0}".format(dtype) in ConfigKnownQtTypes:
158 self.type = dtype # It's a Qt type, so skipping translation is ok
159 return
160
161 vtype = ConfigVarTypeDispStrings.get(dtype, dtype)
162 # Unkown types should be expandable by default
163 if vtype is dtype and dtype not in self.nonExpandableTypes:
164 self.hasChildren = True
165 self.type = QCoreApplication.translate("VariablesViewer", vtype)
166
167 def __getValue(self, dtype, dvalue):
168 """ 121 """
169 Private method to process the variables value. 122 Private method to process the variables value.
170 123
171 Define and limit value, set tooltip text. If type is known to have 124 Define and limit value, set tooltip text. If type is known to have
172 children, the corresponding flag is set. 125 children, the corresponding flag is set.
173 126
174 @param dtype type string 127 @param dtype type string
175 @type str 128 @type str
176 @param dvalue value of variable encoded as utf-8 129 @param dvalue value of variable encoded as utf-8
177 @type str 130 @type str
178 """ 131 @param indicator type indicator appended to the name
179 if dtype == 'collections.defaultdict': 132 @type str
180 dvalue, default_factory = dvalue.split('|') 133 @param length length of the array or string (-1 if uninitialized
181 self.indicator = '{{:<{0}>}}'.format(default_factory) 134 numpy.ndarray)
182 elif dtype == 'array.array': 135 @type int or str
183 dvalue, typecode = dvalue.split('|') 136 """
184 self.indicator = '[<{0}>]'.format(typecode) 137 length_code = length
185 else: 138 if isinstance(length, str):
186 self.indicator = VariableItem.Type2Indicators.get(dtype, '') 139 length = int(length.split('x')[0])
187 140
188 if dtype == 'numpy.ndarray': 141 if indicator and length > -2:
189 if dvalue: 142 self.childCount = max(0, length) # Update count if array
190 self.childCount = int(dvalue.split('x')[0]) 143 if dtype == 'numpy.ndarray' and length == -1:
191 dvalue = VariableItem.noOfItemsStr.format(dvalue) 144 self.value = VariableItem.unsized
192 else: 145 else:
193 dvalue = VariableItem.unsized 146 self.value = VariableItem.noOfItemsStr.format(length_code)
194 self.hasChildren = True 147
195 148 if dtype != 'str':
196 elif dtype in VariableItem.arrayTypes: 149 self.valueShort = self.value
197 self.childCount = int(dvalue) 150 self.tooltip = str(self.value)[:256]
198 dvalue = VariableItem.noOfItemsStr.format(dvalue) 151 return
199 self.hasChildren = True 152
200 153 if VariableItem.rx_nonprintable.search(dvalue) is None:
201 elif dtype == "Shiboken.EnumType":
202 self.hasChildren = True
203
204 elif dtype == 'str':
205 if VariableItem.rx_nonprintable.search(dvalue) is None:
206 with contextlib.suppress(Exception):
207 dvalue = ast.literal_eval(dvalue)
208 dvalue = str(dvalue)
209
210 elif (
211 dvalue.startswith(("{", "(", "[")) and
212 dvalue.endswith(("}", ")", "]"))
213 ):
214 # it is most probably a dict, tuple or list derived class
215 with contextlib.suppress(Exception): 154 with contextlib.suppress(Exception):
216 value = ast.literal_eval(dvalue) 155 dvalue = ast.literal_eval(dvalue)
217 valueTypeStr = str(type(value))[8:-2] 156
218 if valueTypeStr in VariableItem.arrayTypes: 157 dvalue = str(dvalue)
219 self.childCount = len(value)
220 self.hasChildren = True
221
222 elif (
223 (dvalue.endswith("})") and "({" in dvalue) or
224 (dvalue.endswith("])") and "([" in dvalue)
225 ):
226 # that is probably a set derived class
227 with contextlib.suppress(Exception):
228 value = ast.literal_eval(dvalue.split("(", 1)[1][:-1])
229 valueTypeStr = str(type(value))[8:-2]
230 if valueTypeStr in VariableItem.arrayTypes:
231 self.childCount = len(value)
232 self.hasChildren = True
233
234 self.value = dvalue 158 self.value = dvalue
235 159
236 if len(dvalue) > 2048: # 2 kB 160 if len(dvalue) > 2048: # 2 kB
237 self.tooltip = dvalue[:2048] 161 self.tooltip = dvalue[:2048]
238 dvalue = QCoreApplication.translate( 162 dvalue = QCoreApplication.translate(
294 self.framenr = -1 218 self.framenr = -1
295 self.openItems = [] 219 self.openItems = []
296 self.closedItems = [] 220 self.closedItems = []
297 221
298 visibility = self.tr("Globals") if globalScope else self.tr("Locals") 222 visibility = self.tr("Globals") if globalScope else self.tr("Locals")
299 self.rootNode = VariableItem(None, visibility, self.tr("Type"), 223 self.rootNode = VariableItem(None, visibility, '', self.tr("Type"),
300 self.tr("Value")) 224 True, 0, self.tr("Value"))
301 225
302 self.__globalScope = globalScope 226 self.__globalScope = globalScope
303 227
304 def clear(self, reset=False): 228 def clear(self, reset=False):
305 """ 229 """
401 parent.populated = True 325 parent.populated = True
402 else: 326 else:
403 idx = itemStartIndex 327 idx = itemStartIndex
404 parent.currentCount = idx + len(vlist) 328 parent.currentCount = idx + len(vlist)
405 329
406 # Sort items for Python versions where dict doesn't retain order
407 vlist.sort(key=lambda x: x[0])
408 # Now update the table 330 # Now update the table
409 endIndex = idx + len(vlist) 331 endIndex = idx + len(vlist)
410 newChild = None 332 newChild = None
411 knownChildrenCount = len(parent.children) 333 knownChildrenCount = len(parent.children)
412 while idx < endIndex: 334 while idx < endIndex:
666 1: node.valueShort, 588 1: node.valueShort,
667 2: node.type, 589 2: node.type,
668 3: node.sort 590 3: node.sort
669 }.get(column) 591 }.get(column)
670 except AttributeError: 592 except AttributeError:
671 return ['None', '', '', ''][column] 593 return ('None', '', '', '')[column]
672 594
673 elif role == Qt.ItemDataRole.BackgroundRole: 595 elif role == Qt.ItemDataRole.BackgroundRole:
674 if node in node.parent.changedItems: 596 if node in node.parent.changedItems:
675 return self.__bgColorChanged 597 return self.__bgColorChanged
676 elif node in node.parent.newItems: 598 elif node in node.parent.newItems:
720 def headerData(self, section, orientation, 642 def headerData(self, section, orientation,
721 role=Qt.ItemDataRole.DisplayRole): 643 role=Qt.ItemDataRole.DisplayRole):
722 """ 644 """
723 Public method get the header names. 645 Public method get the header names.
724 646
725 @param section the header section (row/coulumn) 647 @param section the header section (row/column)
726 @type int 648 @type int
727 @param orientation the header's orientation 649 @param orientation the header's orientation
728 @type QtCore.Qt.Orientation 650 @type QtCore.Qt.Orientation
729 @param role the requested data role 651 @param role the requested data role
730 @type QtCore.Qt.ItemDataRole 652 @type QtCore.Qt.ItemDataRole

eric ide

mercurial