diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/DebugClients/Python/DebugVariables.py --- a/src/eric7/DebugClients/Python/DebugVariables.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/DebugClients/Python/DebugVariables.py Wed Jul 13 14:55:47 2022 +0200 @@ -27,10 +27,11 @@ """ Base class of the resolver class tree. """ + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type any @param attribute name of the attribute to extract @@ -39,11 +40,11 @@ @rtype any """ return getattr(var, attribute, None) - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @return list containing the variable attributes @@ -54,7 +55,7 @@ with contextlib.suppress(Exception): attribute = getattr(var, name) d.append((name, attribute)) - + return d @@ -67,10 +68,11 @@ """ Class used to resolve the default way. """ + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -82,7 +84,7 @@ with contextlib.suppress(Exception): attribute = getattr(var, name) d.append((name, attribute)) - + yield -1, d while True: yield -2, [] @@ -97,10 +99,11 @@ """ Class used to resolve from a dictionary. """ + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type dict @param attribute name of the attribute to extract @@ -113,18 +116,18 @@ return var[attribute] except Exception: return getattr(var, attribute, None) - + expectedID = int(attribute.split(" (ID:")[-1][:-1]) for key, value in var.items(): if id(key) == expectedID: return value - + return None - + def keyToStr(self, key): """ Public method to get a string representation for a key. - + @param key key to be converted @type any @return string representation of the given key @@ -134,15 +137,15 @@ key = repr(key) # Special handling for bytes object # Raw and f-Strings are always converted to str - if key[0] == 'b': + if key[0] == "b": key = key[1:] return key # __IGNORE_WARNING_M834__ - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -158,7 +161,7 @@ except TypeError: # Slow path: only sort items with same type (Py3 only) allItems.sort(key=lambda x: (str(x[0]), x[0])) - + for key, value in allItems: key = "{0} (ID:{1})".format(self.keyToStr(key), id(key)) d.append((key, value)) @@ -168,14 +171,14 @@ start += count count = 0 d = [] - + if d: yield start, d - + # in case it has additional fields d = super().getVariableList(var) yield -1, d - + while True: yield -2, [] @@ -189,10 +192,11 @@ """ Class used to resolve from a tuple or list. """ + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type tuple or list @param attribute name of the attribute to extract @@ -204,11 +208,11 @@ return var[int(attribute)] except Exception: return getattr(var, str(attribute), None) - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -225,17 +229,17 @@ start = idx + 1 count = 0 d = [] - + if d: yield start, d - + # in case it has additional fields d = super().getVariableList(var) yield -1, d - + while True: yield -2, [] - + ############################################################ ## Resolver for dict_items, dict_keys and dict_values @@ -246,10 +250,11 @@ """ Class used to resolve from dict views. """ + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type dict_items, dict_keys or dict_values @param attribute id of the value to extract @@ -258,11 +263,11 @@ @rtype any """ return super().resolve(list(var), attribute) - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -281,10 +286,11 @@ """ Class used to resolve from a set or frozenset. """ + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type tuple or list @param attribute id of the value to extract @@ -302,13 +308,13 @@ for v in var: if id(v) == attribute: return v - + return None - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -325,17 +331,17 @@ start += count count = 0 d = [] - + if d: yield start, d - + # in case it has additional fields d = super().getVariableList(var) yield -1, d - + while True: yield -2, [] - + ############################################################ ## Resolver for Numpy Arrays @@ -346,24 +352,25 @@ """ Class used to resolve from numpy ndarray including some meta data. """ + def __isNumeric(self, arr): """ Private method to check, if an array is of a numeric type. - + @param arr array to check @type ndarray @return flag indicating a numeric array @rtype bool """ try: - return arr.dtype.kind in 'biufc' + return arr.dtype.kind in "biufc" except AttributeError: return False - + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type ndarray @param attribute id of the value to extract @@ -371,35 +378,35 @@ @return value of the attribute @rtype any """ - if attribute == 'min': + if attribute == "min": if self.__isNumeric(var): return var.min() else: return None - - if attribute == 'max': + + if attribute == "max": if self.__isNumeric(var): return var.max() else: return None - - if attribute == 'mean': + + if attribute == "mean": if self.__isNumeric(var): return var.mean() else: return None - + try: return var[int(attribute)] except Exception: return getattr(var, attribute, None) - + return None - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -413,7 +420,7 @@ allItems = var.tolist() except TypeError: # TypeError: len() of unsized object allItems = [] - + for idx, value in enumerate(allItems): d.append((str(idx), value)) count += 1 @@ -422,42 +429,39 @@ start += count count = 0 d = [] - + if d: yield start, d - + # in case it has additional fields d = super().getVariableList(var) - + if var.size > 1024 * 1024: d.append( - ('min', - 'ndarray too big, calculating min would slow down debugging') + ("min", "ndarray too big, calculating min would slow down debugging") ) d.append( - ('max', - 'ndarray too big, calculating max would slow down debugging') + ("max", "ndarray too big, calculating max would slow down debugging") ) d.append( - ('mean', - 'ndarray too big, calculating mean would slow down debugging') + ("mean", "ndarray too big, calculating mean would slow down debugging") ) elif self.__isNumeric(var): if var.size == 0: - d.append(('min', 'empty array')) - d.append(('max', 'empty array')) - d.append(('mean', 'empty array')) + d.append(("min", "empty array")) + d.append(("max", "empty array")) + d.append(("mean", "empty array")) else: - d.append(('min', var.min())) - d.append(('max', var.max())) - d.append(('mean', var.mean())) + d.append(("min", var.min())) + d.append(("max", var.max())) + d.append(("mean", var.mean())) else: - d.append(('min', 'not a numeric object')) - d.append(('max', 'not a numeric object')) - d.append(('mean', 'not a numeric object')) - + d.append(("min", "not a numeric object")) + d.append(("max", "not a numeric object")) + d.append(("mean", "not a numeric object")) + yield -1, d - + while True: yield -2, [] @@ -471,10 +475,11 @@ """ Class used to resolve from Django multi value dictionaries. """ + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type MultiValueDict @param attribute name of the attribute to extract @@ -487,18 +492,18 @@ return var[attribute] except Exception: return getattr(var, attribute, None) - + expectedID = int(attribute.split(" (ID:")[-1][:-1]) for key in var: if id(key) == expectedID: return var.getlist(key) - + return None - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -514,7 +519,7 @@ except TypeError: # Slow path: only sort items with same type (Py3 only) allKeys.sort(key=lambda x: (str(x), x)) - + for key in allKeys: dkey = "{0} (ID:{1})".format(self.keyToStr(key), id(key)) d.append((dkey, var.getlist(key))) @@ -524,17 +529,17 @@ start += count count = 0 d = [] - + if d: yield start, d - + # in case it has additional fields d = super(DictResolver, self).getVariableList(var) yield -1, d - + while True: yield -2, [] - + ############################################################ ## Resolver for array.array @@ -545,6 +550,7 @@ """ Class used to resolve from array.array including some meta data. """ + TypeCodeMap = { "b": "int (signed char)", "B": "int (unsigned char)", @@ -560,11 +566,11 @@ "f": "float (float)", "d": "float (double)", } - + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type array.array @param attribute id of the value to extract @@ -576,13 +582,13 @@ return var[int(attribute)] except Exception: return getattr(var, attribute, None) - + return None - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -592,7 +598,7 @@ d = [] start = count = 0 allItems = var.tolist() - + for idx, value in enumerate(allItems): d.append((str(idx), value)) count += 1 @@ -601,18 +607,18 @@ start += count count = 0 d = [] - + if d: yield start, d - + # in case it has additional fields d = super().getVariableList(var) - + # Special data for array type: convert typecode to readable text - d.append(('type', self.TypeCodeMap.get(var.typecode, 'illegal type'))) - + d.append(("type", self.TypeCodeMap.get(var.typecode, "illegal type"))) + yield -1, d - + while True: yield -2, [] @@ -626,10 +632,11 @@ """ Class used to resolve the Qt implementations. """ + def resolve(self, var, attribute): """ Public method to get an attribute from a variable. - + @param var variable to extract an attribute or value from @type Qt objects @param attribute name of the attribute to extract @@ -637,15 +644,15 @@ @return value of the attribute @rtype any """ - if attribute == 'internalPointer': + if attribute == "internalPointer": return var.internalPointer() - + return getattr(var, attribute, None) - + def getVariableList(self, var): """ Public method to get the attributes of a variable as a list. - + @param var variable to be converted @type any @yield tuple containing the batch start index and a list @@ -658,99 +665,90 @@ # cases, e.g. already deleted C++ objects, str conversion.. with contextlib.suppress(Exception): qttype = type(var).__name__ - - if qttype in ('QLabel', 'QPushButton'): - attributes = ('text', ) - elif qttype == 'QByteArray': - d.append(('bytes', bytes(var))) - d.append(('hex', "QByteArray", "{0}".format(var.toHex()))) + + if qttype in ("QLabel", "QPushButton"): + attributes = ("text",) + elif qttype == "QByteArray": + d.append(("bytes", bytes(var))) + d.append(("hex", "QByteArray", "{0}".format(var.toHex()))) + d.append(("base64", "QByteArray", "{0}".format(var.toBase64()))) d.append( - ('base64', "QByteArray", - "{0}".format(var.toBase64())) - ) - d.append( - ('percent encoding', "QByteArray", - "{0}".format(var.toPercentEncoding())) + ( + "percent encoding", + "QByteArray", + "{0}".format(var.toPercentEncoding()), + ) ) - elif qttype in ('QPoint', 'QPointF'): - attributes = ('x', 'y') - elif qttype in ('QRect', 'QRectF'): - attributes = ('x', 'y', 'width', 'height') - elif qttype in ('QSize', 'QSizeF'): - attributes = ('width', 'height') - elif qttype == 'QColor': - attributes = ('name', ) + elif qttype in ("QPoint", "QPointF"): + attributes = ("x", "y") + elif qttype in ("QRect", "QRectF"): + attributes = ("x", "y", "width", "height") + elif qttype in ("QSize", "QSizeF"): + attributes = ("width", "height") + elif qttype == "QColor": + attributes = ("name",) r, g, b, a = var.getRgb() - d.append( - ('rgba', "{0:d}, {1:d}, {2:d}, {3:d}".format(r, g, b, a)) - ) + d.append(("rgba", "{0:d}, {1:d}, {2:d}, {3:d}".format(r, g, b, a))) h, s, v, a = var.getHsv() - d.append( - ('hsva', "{0:d}, {1:d}, {2:d}, {3:d}".format(h, s, v, a)) - ) + d.append(("hsva", "{0:d}, {1:d}, {2:d}, {3:d}".format(h, s, v, a))) c, m, y, k, a = var.getCmyk() d.append( - ('cmyka', - "{0:d}, {1:d}, {2:d}, {3:d}, {4:d}".format(c, m, y, k, a)) + ("cmyka", "{0:d}, {1:d}, {2:d}, {3:d}, {4:d}".format(c, m, y, k, a)) ) - elif qttype in ('QDate', 'QTime', 'QDateTime'): + elif qttype in ("QDate", "QTime", "QDateTime"): d.append((qttype[1:].lower(), var.toString())) - elif qttype == 'QDir': - attributes = ('path', 'absolutePath', 'canonicalPath') - elif qttype == 'QFile': - attributes = ('fileName', ) - elif qttype == 'QFont': - attributes = ( - 'family', 'pointSize', 'weight', 'bold', 'italic' - ) - elif qttype == 'QUrl': - d.append(('url', var.toString())) - attributes = ('scheme', 'userName', 'password', 'host', 'port', - 'path') - elif qttype == 'QModelIndex': + elif qttype == "QDir": + attributes = ("path", "absolutePath", "canonicalPath") + elif qttype == "QFile": + attributes = ("fileName",) + elif qttype == "QFont": + attributes = ("family", "pointSize", "weight", "bold", "italic") + elif qttype == "QUrl": + d.append(("url", var.toString())) + attributes = ("scheme", "userName", "password", "host", "port", "path") + elif qttype == "QModelIndex": valid = var.isValid() - d.append(('valid', valid)) + d.append(("valid", valid)) if valid: d.append(("internalPointer", var.internalPointer())) - attributes = ('row', 'column', 'internalId') - elif qttype in ('QRegExp', "QRegularExpression"): - attributes = ('pattern', ) - + attributes = ("row", "column", "internalId") + elif qttype in ("QRegExp", "QRegularExpression"): + attributes = ("pattern",) + # GUI stuff - elif qttype == 'QAction': - d.append(('shortcut', var.shortcut().toString())) - attributes = ('objectName', 'text', 'iconText', 'toolTip', - 'whatsThis') - - elif qttype == 'QKeySequence': - d.append(('keySequence', var.toString())) - + elif qttype == "QAction": + d.append(("shortcut", var.shortcut().toString())) + attributes = ("objectName", "text", "iconText", "toolTip", "whatsThis") + + elif qttype == "QKeySequence": + d.append(("keySequence", var.toString())) + # XML stuff - elif qttype == 'QDomAttr': - attributes = ('name', 'var') - elif qttype in ('QDomCharacterData', 'QDomComment', 'QDomText'): - attributes = ('data', ) - elif qttype == 'QDomDocument': - d.append(('text', var.toString())) - elif qttype == 'QDomElement': - attributes = ('tagName', 'text') - + elif qttype == "QDomAttr": + attributes = ("name", "var") + elif qttype in ("QDomCharacterData", "QDomComment", "QDomText"): + attributes = ("data",) + elif qttype == "QDomDocument": + d.append(("text", var.toString())) + elif qttype == "QDomElement": + attributes = ("tagName", "text") + # Networking stuff - elif qttype == 'QHostAddress': - d.append(('address', var.toString())) - + elif qttype == "QHostAddress": + d.append(("address", var.toString())) + # PySide specific - elif qttype == 'EnumType': # Not in PyQt possible + elif qttype == "EnumType": # Not in PyQt possible for key, value in var.values.items(): d.append((key, int(value))) - + for attribute in attributes: d.append((attribute, getattr(var, attribute)())) - + # add additional fields - if qttype != 'EnumType': + if qttype != "EnumType": d.extend(super().getVariableList(var)) - + yield -1, d while True: yield -2, [] @@ -782,7 +780,7 @@ Protected function to initialize the type map. """ global _TypeMap - + # Type map for special handling of array types. # All other types not listed here use the default resolver. _TypeMap = [ @@ -806,26 +804,29 @@ Public function to update the type map based on module imports. """ global _TypeMap, _ArrayTypes, _TryArray, _TryNumpy, _TryDjango, _MapCount - + # array.array may not be imported (yet) - if _TryArray and 'array' in sys.modules: + if _TryArray and "array" in sys.modules: import array + _TypeMap.append((array.array, arrayResolver)) _TryArray = False - + # numpy may not be imported (yet) - if _TryNumpy and 'numpy' in sys.modules: + if _TryNumpy and "numpy" in sys.modules: import numpy + _TypeMap.append((numpy.ndarray, ndarrayResolver)) _TryNumpy = False - + # django may not be imported (yet) - if _TryDjango and 'django' in sys.modules: + if _TryDjango and "django" in sys.modules: from django.utils.datastructures import MultiValueDict + # it should go before dict _TypeMap.insert(0, (MultiValueDict, multiValueDictResolver)) _TryDjango = False - + # If _TypeMap changed, rebuild the _ArrayTypes tuple if _MapCount != len(_TypeMap): _ArrayTypes = tuple(typ for typ, _resolver in _TypeMap) @@ -835,27 +836,25 @@ def getResolver(obj): """ Public method to get the resolver based on the type info of an object. - + @param obj object to get resolver for @type any @return resolver @rtype BaseResolver """ # Between PyQt and PySide the returned type is different (class vs. type) - typeStr = str(type(obj)).split(' ', 1)[-1] + typeStr = str(type(obj)).split(" ", 1)[-1] typeStr = typeStr[1:-2] - - if ( - typeStr.startswith(ConfigQtNames) and - typeStr.endswith(ConfigKnownQtTypes) - ): + + if typeStr.startswith(ConfigQtNames) and typeStr.endswith(ConfigKnownQtTypes): return qtResolver - + for typeData, resolver in _TypeMap: # __IGNORE_WARNING_M507__ if isinstance(obj, typeData): return resolver - + return defaultResolver + # # eflag: noqa = Y113