1584 break |
1596 break |
1585 |
1597 |
1586 idx = -3 # Requested variable doesn't exist anymore |
1598 idx = -3 # Requested variable doesn't exist anymore |
1587 # If found, get the details of attribute |
1599 # If found, get the details of attribute |
1588 if variable is not None: |
1600 if variable is not None: |
1589 typeName, typeStr, resolver = DebugVariables.getType(variable) |
1601 resolver = DebugVariables.getResolver(variable) |
1590 if resolver: |
1602 if resolver: |
1591 varGen = resolver.getDictionary(variable) |
1603 varGen = resolver.getVariableList(variable) |
|
1604 # cache for next lookup |
1592 self.resolverCache[scope][str(var)] = varGen |
1605 self.resolverCache[scope][str(var)] = varGen |
1593 |
1606 |
1594 idx, varDict = next(varGen) |
1607 idx, varDict = next(varGen) |
1595 varlist = self.__formatVariablesList( |
1608 if idx != -2: # more elements available |
1596 varDict, scope, filterList) |
1609 varlist = self.__formatVariablesList( |
1597 else: |
1610 varDict, scope, filterList) |
1598 # Gently handle exception which could occur as special |
|
1599 # cases, e.g. already deleted C++ objects, str conversion.. |
|
1600 try: |
|
1601 varlist = self.__formatQtVariable(variable, typeName) |
|
1602 except Exception: |
|
1603 varlist = [] |
|
1604 idx = -1 |
|
1605 |
1611 |
1606 var.insert(0, idx) |
1612 var.insert(0, idx) |
1607 |
1613 |
1608 self.sendJsonCommand("ResponseVariable", { |
1614 self.sendJsonCommand("ResponseVariable", { |
1609 "scope": scope, |
1615 "scope": scope, |
1610 "variable": var, |
1616 "variable": var, |
1611 "variables": varlist, |
1617 "variables": varlist, |
1612 }) |
1618 }) |
1613 |
1619 |
1614 def __extractIndicators(self, var): |
1620 def __formatVariablesList(self, variables, scope, filterList=None): |
1615 """ |
|
1616 Private method to extract the indicator string from a variable text. |
|
1617 |
|
1618 @param var variable text |
|
1619 @type str |
|
1620 @return tuple containing the variable text without indicators and the |
|
1621 indicator string |
|
1622 @rtype tuple of two str |
|
1623 """ |
|
1624 for indicator in DebugClientBase.Indicators: |
|
1625 if var.endswith(indicator): |
|
1626 return var[:-len(indicator)], indicator |
|
1627 |
|
1628 return var, "" |
|
1629 |
|
1630 def __formatQtVariable(self, value, qttype): |
|
1631 """ |
|
1632 Private method to produce a formatted output of a simple Qt5/Qt6 type. |
|
1633 |
|
1634 @param value variable to be formatted |
|
1635 @param qttype type of the Qt variable to be formatted (string) |
|
1636 @return A tuple consisting of a list of formatted variables. Each |
|
1637 variable entry is a tuple of three elements, the variable name, |
|
1638 its type and value. |
|
1639 """ |
|
1640 varlist = [] |
|
1641 if qttype == 'QChar': |
|
1642 varlist.append( |
|
1643 ("", "QChar", "{0}".format(chr(value.unicode())))) |
|
1644 varlist.append(("", "int", "{0:d}".format(value.unicode()))) |
|
1645 elif qttype == 'QByteArray': |
|
1646 varlist.append( |
|
1647 ("bytes", "QByteArray", "{0}".format(bytes(value))[2:-1])) |
|
1648 varlist.append( |
|
1649 ("hex", "QByteArray", "{0}".format(value.toHex())[2:-1])) |
|
1650 varlist.append( |
|
1651 ("base64", "QByteArray", "{0}".format(value.toBase64())[2:-1])) |
|
1652 varlist.append(("percent encoding", "QByteArray", |
|
1653 "{0}".format(value.toPercentEncoding())[2:-1])) |
|
1654 elif qttype == 'QString': |
|
1655 varlist.append(("", "QString", "{0}".format(value))) |
|
1656 elif qttype == 'QStringList': |
|
1657 for i in range(value.count()): |
|
1658 varlist.append( |
|
1659 ("{0:d}".format(i), "QString", "{0}".format(value[i]))) |
|
1660 elif qttype == 'QPoint': |
|
1661 varlist.append(("x", "int", "{0:d}".format(value.x()))) |
|
1662 varlist.append(("y", "int", "{0:d}".format(value.y()))) |
|
1663 elif qttype == 'QPointF': |
|
1664 varlist.append(("x", "float", "{0:g}".format(value.x()))) |
|
1665 varlist.append(("y", "float", "{0:g}".format(value.y()))) |
|
1666 elif qttype == 'QRect': |
|
1667 varlist.append(("x", "int", "{0:d}".format(value.x()))) |
|
1668 varlist.append(("y", "int", "{0:d}".format(value.y()))) |
|
1669 varlist.append(("width", "int", "{0:d}".format(value.width()))) |
|
1670 varlist.append(("height", "int", "{0:d}".format(value.height()))) |
|
1671 elif qttype == 'QRectF': |
|
1672 varlist.append(("x", "float", "{0:g}".format(value.x()))) |
|
1673 varlist.append(("y", "float", "{0:g}".format(value.y()))) |
|
1674 varlist.append(("width", "float", "{0:g}".format(value.width()))) |
|
1675 varlist.append(("height", "float", "{0:g}".format(value.height()))) |
|
1676 elif qttype == 'QSize': |
|
1677 varlist.append(("width", "int", "{0:d}".format(value.width()))) |
|
1678 varlist.append(("height", "int", "{0:d}".format(value.height()))) |
|
1679 elif qttype == 'QSizeF': |
|
1680 varlist.append(("width", "float", "{0:g}".format(value.width()))) |
|
1681 varlist.append(("height", "float", "{0:g}".format(value.height()))) |
|
1682 elif qttype == 'QColor': |
|
1683 varlist.append(("name", "str", "{0}".format(value.name()))) |
|
1684 r, g, b, a = value.getRgb() |
|
1685 varlist.append( |
|
1686 ("rgba", "int", |
|
1687 "{0:d}, {1:d}, {2:d}, {3:d}".format(r, g, b, a))) |
|
1688 h, s, v, a = value.getHsv() |
|
1689 varlist.append( |
|
1690 ("hsva", "int", |
|
1691 "{0:d}, {1:d}, {2:d}, {3:d}".format(h, s, v, a))) |
|
1692 c, m, y, k, a = value.getCmyk() |
|
1693 varlist.append( |
|
1694 ("cmyka", "int", |
|
1695 "{0:d}, {1:d}, {2:d}, {3:d}, {4:d}".format(c, m, y, k, a))) |
|
1696 elif qttype == 'QDate': |
|
1697 varlist.append(("", "QDate", "{0}".format(value.toString()))) |
|
1698 elif qttype == 'QTime': |
|
1699 varlist.append(("", "QTime", "{0}".format(value.toString()))) |
|
1700 elif qttype == 'QDateTime': |
|
1701 varlist.append(("", "QDateTime", "{0}".format(value.toString()))) |
|
1702 elif qttype == 'QDir': |
|
1703 varlist.append(("path", "str", "{0}".format(value.path()))) |
|
1704 varlist.append(("absolutePath", "str", |
|
1705 "{0}".format(value.absolutePath()))) |
|
1706 varlist.append(("canonicalPath", "str", |
|
1707 "{0}".format(value.canonicalPath()))) |
|
1708 elif qttype == 'QFile': |
|
1709 varlist.append(("fileName", "str", "{0}".format(value.fileName()))) |
|
1710 elif qttype == 'QFont': |
|
1711 varlist.append(("family", "str", "{0}".format(value.family()))) |
|
1712 varlist.append( |
|
1713 ("pointSize", "int", "{0:d}".format(value.pointSize()))) |
|
1714 varlist.append(("weight", "int", "{0:d}".format(value.weight()))) |
|
1715 varlist.append(("bold", "bool", "{0}".format(value.bold()))) |
|
1716 varlist.append(("italic", "bool", "{0}".format(value.italic()))) |
|
1717 elif qttype == 'QUrl': |
|
1718 varlist.append(("url", "str", "{0}".format(value.toString()))) |
|
1719 varlist.append(("scheme", "str", "{0}".format(value.scheme()))) |
|
1720 varlist.append(("user", "str", "{0}".format(value.userName()))) |
|
1721 varlist.append(("password", "str", "{0}".format(value.password()))) |
|
1722 varlist.append(("host", "str", "{0}".format(value.host()))) |
|
1723 varlist.append(("port", "int", "{0:d}".format(value.port()))) |
|
1724 varlist.append(("path", "str", "{0}".format(value.path()))) |
|
1725 elif qttype == 'QModelIndex': |
|
1726 varlist.append(("valid", "bool", "{0}".format(value.isValid()))) |
|
1727 if value.isValid(): |
|
1728 varlist.append(("row", "int", "{0}".format(value.row()))) |
|
1729 varlist.append(("column", "int", "{0}".format(value.column()))) |
|
1730 varlist.append( |
|
1731 ("internalId", "int", "{0}".format(value.internalId()))) |
|
1732 varlist.append(("internalPointer", "void *", |
|
1733 "{0}".format(value.internalPointer()))) |
|
1734 elif qttype in ('QRegExp', "QRegularExpression"): |
|
1735 varlist.append(("pattern", "str", "{0}".format(value.pattern()))) |
|
1736 |
|
1737 # GUI stuff |
|
1738 elif qttype == 'QAction': |
|
1739 varlist.append(("name", "str", "{0}".format(value.objectName()))) |
|
1740 varlist.append(("text", "str", "{0}".format(value.text()))) |
|
1741 varlist.append( |
|
1742 ("icon text", "str", "{0}".format(value.iconText()))) |
|
1743 varlist.append(("tooltip", "str", "{0}".format(value.toolTip()))) |
|
1744 varlist.append( |
|
1745 ("whatsthis", "str", "{0}".format(value.whatsThis()))) |
|
1746 varlist.append( |
|
1747 ("shortcut", "str", |
|
1748 "{0}".format(value.shortcut().toString()))) |
|
1749 elif qttype == 'QKeySequence': |
|
1750 varlist.append(("value", "", "{0}".format(value.toString()))) |
|
1751 |
|
1752 # XML stuff |
|
1753 elif qttype == 'QDomAttr': |
|
1754 varlist.append(("name", "str", "{0}".format(value.name()))) |
|
1755 varlist.append(("value", "str", "{0}".format(value.value()))) |
|
1756 elif qttype in ('QDomCharacterData', 'QDomComment', 'QDomText'): |
|
1757 varlist.append(("data", "str", "{0}".format(value.data()))) |
|
1758 elif qttype == 'QDomDocument': |
|
1759 varlist.append(("text", "str", "{0}".format(value.toString()))) |
|
1760 elif qttype == 'QDomElement': |
|
1761 varlist.append(("tagName", "str", "{0}".format(value.tagName()))) |
|
1762 varlist.append(("text", "str", "{0}".format(value.text()))) |
|
1763 |
|
1764 # Networking stuff |
|
1765 elif qttype == 'QHostAddress': |
|
1766 varlist.append( |
|
1767 ("address", "QHostAddress", "{0}".format(value.toString()))) |
|
1768 |
|
1769 # PySide specific |
|
1770 elif qttype == 'EnumType': # Not in PyQt possible |
|
1771 for key, value in value.values.items(): |
|
1772 varlist.append((key, qttype, "{0}".format(int(value)))) |
|
1773 |
|
1774 return varlist |
|
1775 |
|
1776 def __formatVariablesList(self, dict_, scope, filterList=None): |
|
1777 """ |
1621 """ |
1778 Private method to produce a formated variables list. |
1622 Private method to produce a formated variables list. |
1779 |
1623 |
1780 The dictionary passed in to it is scanned. Variables are |
1624 The dictionary passed in to it is scanned. Variables are |
1781 only added to the list, if their type is not contained |
1625 only added to the list, if their type is not contained |
1839 "special_attributes" in filterList) or |
1682 "special_attributes" in filterList) or |
1840 (key == "__hash__" and |
1683 (key == "__hash__" and |
1841 "builtin_function_or_method" in filterList) |
1684 "builtin_function_or_method" in filterList) |
1842 ): |
1685 ): |
1843 continue |
1686 continue |
1844 else: |
1687 elif valtype is None: |
1845 isQt = False |
|
1846 # valtypestr, e.g. class 'PyQt6.QtCore.QPoint' |
1688 # valtypestr, e.g. class 'PyQt6.QtCore.QPoint' |
1847 valtypestr = str(type(value))[1:-1] |
1689 valtypestr = str(type(value)) |
1848 _, valtype = valtypestr.split(' ', 1) |
1690 _, valtype = valtypestr.split(' ', 1) |
1849 # valtype, e.g. PyQt6.QtCore.QPoint |
1691 # valtype is the real type, e.g. PyQt6.QtCore.QPoint |
1850 valtype = valtype[1:-1] |
1692 # valtype_filter is used for filtering, where the base class is |
|
1693 # also important |
|
1694 valtype = valtype_filter = valtype[1:-2] |
1851 # Strip 'instance' to be equal with Python 3 |
1695 # Strip 'instance' to be equal with Python 3 |
1852 if valtype == "instancemethod": |
1696 if valtype == "instancemethod": |
1853 valtype = "method" |
1697 valtype = valtype_filter = "method" |
1854 elif valtype in ("type", "classobj"): |
1698 elif isinstance(value, type): |
1855 valtype = "class" |
1699 valtype_filter = "class" |
|
1700 if valtype == "type": |
|
1701 valtype = "class" |
1856 elif valtype == "method-wrapper": |
1702 elif valtype == "method-wrapper": |
1857 valtype = "builtin_function_or_method" |
1703 valtype = valtype_filter = "builtin_function_or_method" |
1858 |
1704 |
1859 # valtypename, e.g. QPoint |
1705 # Don't process variables which types are on filter list |
1860 valtypename = type(value).__name__ |
|
1861 if ( |
1706 if ( |
1862 valtype in filterList or |
1707 valtype_filter in filterList or |
1863 (valtype in ("sip.enumtype", "sip.wrappertype") and |
1708 (valtype_filter in ("sip.enumtype", "sip.wrappertype") and |
1864 'class' in filterList) or |
1709 'class' in filterList) or |
1865 (valtype in ( |
1710 (valtype_filter in ( |
1866 "sip.methoddescriptor", "method_descriptor") and |
1711 "sip.methoddescriptor", "method_descriptor") and |
1867 'method' in filterList) or |
1712 'method' in filterList) or |
1868 (valtype in ("numpy.ndarray", "array.array") and |
1713 (valtype_filter in ("numpy.ndarray", "array.array") and |
1869 'list' in filterList) or |
1714 'list' in filterList) or |
1870 (valtypename == "MultiValueDict" and |
1715 (valtype_filter == "django.MultiValueDict" and |
1871 'dict' in filterList) or |
1716 'dict' in filterList) or |
1872 'instance' in filterList |
1717 'instance' in filterList |
1873 ): |
1718 ): |
1874 continue |
1719 continue |
|
1720 |
|
1721 length = -2 |
|
1722 indicator = '' |
|
1723 |
|
1724 if valtype == 'str': |
|
1725 rvalue = repr(value) |
|
1726 length = len(rvalue) |
|
1727 elif valtype in NonExpandableTypes: |
|
1728 rvalue = repr(value) |
|
1729 |
|
1730 if rvalue is not None: |
|
1731 varlist.append( |
|
1732 (key, indicator, valtype, hasChildren, length, rvalue) |
|
1733 ) |
|
1734 continue |
|
1735 |
|
1736 try: |
|
1737 for dtype in DebugVariables._ArrayTypes: |
|
1738 if isinstance(value, dtype): |
|
1739 try: |
|
1740 length = len(value) |
|
1741 except TypeError: |
|
1742 length = -1 # Uninitialized array |
|
1743 |
|
1744 dtype = str(dtype)[8:-2] |
|
1745 # Standard array type indicators |
|
1746 indicator = self.Type2Indicators.get(dtype, '') |
|
1747 |
|
1748 # Special handling of some array types |
|
1749 if valtype == 'array.array': |
|
1750 indicator = '[<{0}>]'.format(value.typecode) |
|
1751 elif valtype == 'collections.defaultdict': |
|
1752 if value.default_factory is None: |
|
1753 def_factory = "None" |
|
1754 else: |
|
1755 def_factory = value.default_factory.__name__ |
|
1756 indicator = '{{:<{0}>}}'.format(def_factory) |
|
1757 elif valtype == "numpy.ndarray" and length > -1: |
|
1758 length = "x".join(str(x) for x in value.shape) |
|
1759 elif valtype.endswith(".MultiValueDict"): |
|
1760 indicator = "{:}" |
|
1761 valtype = "django.MultiValueDict" # shortened type |
|
1762 break |
|
1763 else: |
|
1764 rvalue = repr(value) |
1875 |
1765 |
1876 isQt = valtype.startswith(ConfigQtNames) |
1766 hasChildren = True |
1877 |
1767 except Exception: |
1878 try: |
1768 rvalue = '' |
1879 if valtype in self.arrayTypes: |
1769 |
1880 rvalue = "{0:d}".format(len(value)) |
1770 varlist.append( |
1881 elif valtype == 'array.array': |
1771 (key, indicator, valtype, hasChildren, length, rvalue) |
1882 rvalue = "{0:d}|{1}".format( |
1772 ) |
1883 len(value), value.typecode) |
|
1884 elif valtype == 'collections.defaultdict': |
|
1885 if value.default_factory is None: |
|
1886 factoryName = "None" |
|
1887 else: |
|
1888 factoryName = value.default_factory.__name__ |
|
1889 rvalue = "{0:d}|{1}".format(len(value), factoryName) |
|
1890 elif valtype == "numpy.ndarray": |
|
1891 rvalue = "x".join(str(x) for x in value.shape) |
|
1892 elif valtypename == "MultiValueDict": |
|
1893 rvalue = "{0:d}".format(len(value.keys())) |
|
1894 valtype = "django.MultiValueDict" # shortened type |
|
1895 else: |
|
1896 rvalue = repr(value) |
|
1897 if valtype.startswith('class') and rvalue[0] in '{([': |
|
1898 rvalue = "" |
|
1899 elif (isQt and rvalue.startswith("<class '")): |
|
1900 rvalue = rvalue[8:-2] |
|
1901 except Exception: |
|
1902 rvalue = '' |
|
1903 |
|
1904 varlist.append((key, valtype, rvalue)) |
|
1905 |
1773 |
1906 return varlist |
1774 return varlist |
1907 |
1775 |
1908 def __generateFilterObjects(self, scope, filterString): |
1776 def __generateFilterObjects(self, scope, filterString): |
1909 """ |
1777 """ |