--- a/eric7/Debugger/VariablesViewer.py Sun Aug 29 17:50:13 2021 +0200 +++ b/eric7/Debugger/VariablesViewer.py Sun Aug 29 19:19:31 2021 +0200 @@ -21,7 +21,6 @@ from EricWidgets.EricApplication import ericApp from .Config import ConfigVarTypeDispStrings -from DebugClients.Python.DebugConfig import ConfigQtNames, ConfigKnownQtTypes import Preferences import Utilities @@ -33,34 +32,14 @@ """ Class implementing the data structure for all variable items. """ - Type2Indicators = { - # Python types - 'list': '[]', - 'tuple': '()', - 'dict': '{:}', # __IGNORE_WARNING_M613__ - 'set': '{}', # __IGNORE_WARNING_M613__ - 'frozenset': '{}', # __IGNORE_WARNING_M613__ - 'numpy.ndarray': '[ndarray]', # __IGNORE_WARNING_M613__ - } - # Initialize regular expression for unprintable strings rx_nonprintable = re.compile(r"""(\\x\d\d)+""") noOfItemsStr = QCoreApplication.translate("VariablesViewer", "{0} items") unsized = QCoreApplication.translate("VariablesViewer", "unsized") - arrayTypes = { - 'list', 'tuple', 'dict', 'set', 'frozenset', 'numpy.ndarray', - 'django.MultiValueDict', 'array.array', 'collections.defaultdict', - "class 'dict_items'", "class 'dict_keys'", "class 'dict_values'", - } - - nonExpandableTypes = ( - 'method_descriptor', 'wrapper_descriptor', '', 'getset_descriptor', - 'method-wrapper', 'member_descriptor', - ) - - def __init__(self, parent, dvar, dtype, dvalue): + def __init__(self, parent, dvar, indicator, dtype, hasChildren, length, + dvalue): """ Constructor @@ -68,8 +47,15 @@ @type VariableItem @param dvar variable name @type str + @param indicator type indicator appended to the name + @type str @param dtype type string @type str + @param hasChildren indicator for children + @type bool + @param length length of the array or string (-1 if uninitialized + numpy.ndarray) + @type int @param dvalue value string @type str """ @@ -79,7 +65,7 @@ self.childCount = 0 self.currentCount = -1 # -1 indicates to (re)load children # Indicator that there are children - self.hasChildren = False + self.hasChildren = hasChildren self.populated = False # Indicator that item was at least once fully populated self.wasPopulated = False @@ -97,15 +83,15 @@ self.name = '' self.sort = '' - self.type = '' - self.indicator = '' - self.value = None + vtype = ConfigVarTypeDispStrings.get(dtype, dtype) + self.type = QCoreApplication.translate("VariablesViewer", vtype) + self.indicator = indicator + self.value = dvalue self.valueShort = None self.tooltip = '' self.__getName(dvar) - self.__getType(dtype) - self.__getValue(dtype, dvalue) + self.__getValue(dtype, dvalue, indicator, length) def __getName(self, dvar): """ @@ -126,45 +112,12 @@ self.name = dvar try: # Convert numbers to strings with preceding zeros - sort = int(dvar) - sort = "{0:06}".format(sort) + asInt = int(dvar) + self.sort = "{0:06}".format(asInt) except ValueError: - sort = dvar.lower() - - self.sort = sort + self.sort = dvar.lower() - def __getType(self, dtype): - """ - Private method to process the type of the variable. - - If type is known to have children, the corresponding flag is set. - - @param dtype type string - @type str - """ - # Python class? - if dtype.startswith('class '): - dtype = dtype[7:-1] - # Qt related stuff? - elif ( - (dtype.startswith(ConfigQtNames) and - dtype.endswith(ConfigKnownQtTypes)) or - dtype in ('instance', 'class') - ): - self.hasChildren = True - - # Special Qt types should not be expanded infinite - elif ".{0}".format(dtype) in ConfigKnownQtTypes: - self.type = dtype # It's a Qt type, so skipping translation is ok - return - - vtype = ConfigVarTypeDispStrings.get(dtype, dtype) - # Unkown types should be expandable by default - if vtype is dtype and dtype not in self.nonExpandableTypes: - self.hasChildren = True - self.type = QCoreApplication.translate("VariablesViewer", vtype) - - def __getValue(self, dtype, dvalue): + def __getValue(self, dtype, dvalue, indicator, length): """ Private method to process the variables value. @@ -175,62 +128,33 @@ @type str @param dvalue value of variable encoded as utf-8 @type str + @param indicator type indicator appended to the name + @type str + @param length length of the array or string (-1 if uninitialized + numpy.ndarray) + @type int or str """ - if dtype == 'collections.defaultdict': - dvalue, default_factory = dvalue.split('|') - self.indicator = '{{:<{0}>}}'.format(default_factory) - elif dtype == 'array.array': - dvalue, typecode = dvalue.split('|') - self.indicator = '[<{0}>]'.format(typecode) - else: - self.indicator = VariableItem.Type2Indicators.get(dtype, '') - - if dtype == 'numpy.ndarray': - if dvalue: - self.childCount = int(dvalue.split('x')[0]) - dvalue = VariableItem.noOfItemsStr.format(dvalue) - else: - dvalue = VariableItem.unsized - self.hasChildren = True - - elif dtype in VariableItem.arrayTypes: - self.childCount = int(dvalue) - dvalue = VariableItem.noOfItemsStr.format(dvalue) - self.hasChildren = True - - elif dtype == "Shiboken.EnumType": - self.hasChildren = True + length_code = length + if isinstance(length, str): + length = int(length.split('x')[0]) - elif dtype == 'str': - if VariableItem.rx_nonprintable.search(dvalue) is None: - with contextlib.suppress(Exception): - dvalue = ast.literal_eval(dvalue) - dvalue = str(dvalue) + if indicator and length > -2: + self.childCount = max(0, length) # Update count if array + if dtype == 'numpy.ndarray' and length == -1: + self.value = VariableItem.unsized + else: + self.value = VariableItem.noOfItemsStr.format(length_code) - elif ( - dvalue.startswith(("{", "(", "[")) and - dvalue.endswith(("}", ")", "]")) - ): - # it is most probably a dict, tuple or list derived class + if dtype != 'str': + self.valueShort = self.value + self.tooltip = str(self.value)[:256] + return + + if VariableItem.rx_nonprintable.search(dvalue) is None: with contextlib.suppress(Exception): - value = ast.literal_eval(dvalue) - valueTypeStr = str(type(value))[8:-2] - if valueTypeStr in VariableItem.arrayTypes: - self.childCount = len(value) - self.hasChildren = True + dvalue = ast.literal_eval(dvalue) - elif ( - (dvalue.endswith("})") and "({" in dvalue) or - (dvalue.endswith("])") and "([" in dvalue) - ): - # that is probably a set derived class - with contextlib.suppress(Exception): - value = ast.literal_eval(dvalue.split("(", 1)[1][:-1]) - valueTypeStr = str(type(value))[8:-2] - if valueTypeStr in VariableItem.arrayTypes: - self.childCount = len(value) - self.hasChildren = True - + dvalue = str(dvalue) self.value = dvalue if len(dvalue) > 2048: # 2 kB @@ -296,8 +220,8 @@ self.closedItems = [] visibility = self.tr("Globals") if globalScope else self.tr("Locals") - self.rootNode = VariableItem(None, visibility, self.tr("Type"), - self.tr("Value")) + self.rootNode = VariableItem(None, visibility, '', self.tr("Type"), + True, 0, self.tr("Value")) self.__globalScope = globalScope @@ -403,8 +327,6 @@ idx = itemStartIndex parent.currentCount = idx + len(vlist) - # Sort items for Python versions where dict doesn't retain order - vlist.sort(key=lambda x: x[0]) # Now update the table endIndex = idx + len(vlist) newChild = None @@ -668,7 +590,7 @@ 3: node.sort }.get(column) except AttributeError: - return ['None', '', '', ''][column] + return ('None', '', '', '')[column] elif role == Qt.ItemDataRole.BackgroundRole: if node in node.parent.changedItems: @@ -722,7 +644,7 @@ """ Public method get the header names. - @param section the header section (row/coulumn) + @param section the header section (row/column) @type int @param orientation the header's orientation @type QtCore.Qt.Orientation