6519734932
* Deprecate ordereddict module * Import OrderedDict from collections module instead of pgcollections * Deprecate pgcollections module * Deprecate lru_cache module A simpler recipe exists from the standard library using OrderedDict. * Deprecate pil_fix module * Python 3.7 compatibility fix * Avoid or suppress deprecation warnings in tests
128 lines
4.5 KiB
Python
128 lines
4.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
from ..Qt import QtGui, QtCore
|
|
from collections import OrderedDict
|
|
from .TableWidget import TableWidget
|
|
from ..python2_3 import asUnicode
|
|
import types, traceback
|
|
import numpy as np
|
|
|
|
try:
|
|
import metaarray
|
|
HAVE_METAARRAY = True
|
|
except:
|
|
HAVE_METAARRAY = False
|
|
|
|
__all__ = ['DataTreeWidget']
|
|
|
|
class DataTreeWidget(QtGui.QTreeWidget):
|
|
"""
|
|
Widget for displaying hierarchical python data structures
|
|
(eg, nested dicts, lists, and arrays)
|
|
"""
|
|
def __init__(self, parent=None, data=None):
|
|
QtGui.QTreeWidget.__init__(self, parent)
|
|
self.setVerticalScrollMode(self.ScrollPerPixel)
|
|
self.setData(data)
|
|
self.setColumnCount(3)
|
|
self.setHeaderLabels(['key / index', 'type', 'value'])
|
|
self.setAlternatingRowColors(True)
|
|
|
|
def setData(self, data, hideRoot=False):
|
|
"""data should be a dictionary."""
|
|
self.clear()
|
|
self.widgets = []
|
|
self.nodes = {}
|
|
self.buildTree(data, self.invisibleRootItem(), hideRoot=hideRoot)
|
|
self.expandToDepth(3)
|
|
self.resizeColumnToContents(0)
|
|
|
|
def buildTree(self, data, parent, name='', hideRoot=False, path=()):
|
|
if hideRoot:
|
|
node = parent
|
|
else:
|
|
node = QtGui.QTreeWidgetItem([name, "", ""])
|
|
parent.addChild(node)
|
|
|
|
# record the path to the node so it can be retrieved later
|
|
# (this is used by DiffTreeWidget)
|
|
self.nodes[path] = node
|
|
|
|
typeStr, desc, childs, widget = self.parse(data)
|
|
node.setText(1, typeStr)
|
|
node.setText(2, desc)
|
|
|
|
# Truncate description and add text box if needed
|
|
if len(desc) > 100:
|
|
desc = desc[:97] + '...'
|
|
if widget is None:
|
|
widget = QtGui.QPlainTextEdit(asUnicode(data))
|
|
widget.setMaximumHeight(200)
|
|
widget.setReadOnly(True)
|
|
|
|
# Add widget to new subnode
|
|
if widget is not None:
|
|
self.widgets.append(widget)
|
|
subnode = QtGui.QTreeWidgetItem(["", "", ""])
|
|
node.addChild(subnode)
|
|
self.setItemWidget(subnode, 0, widget)
|
|
subnode.setFirstColumnSpanned(True)
|
|
|
|
# recurse to children
|
|
for key, data in childs.items():
|
|
self.buildTree(data, node, asUnicode(key), path=path+(key,))
|
|
|
|
def parse(self, data):
|
|
"""
|
|
Given any python object, return:
|
|
* type
|
|
* a short string representation
|
|
* a dict of sub-objects to be parsed
|
|
* optional widget to display as sub-node
|
|
"""
|
|
# defaults for all objects
|
|
typeStr = type(data).__name__
|
|
if typeStr == 'instance':
|
|
typeStr += ": " + data.__class__.__name__
|
|
widget = None
|
|
desc = ""
|
|
childs = {}
|
|
|
|
# type-specific changes
|
|
if isinstance(data, dict):
|
|
desc = "length=%d" % len(data)
|
|
if isinstance(data, OrderedDict):
|
|
childs = data
|
|
else:
|
|
try:
|
|
childs = OrderedDict(sorted(data.items()))
|
|
except TypeError: # if sorting falls
|
|
childs = OrderedDict(data.items())
|
|
elif isinstance(data, (list, tuple)):
|
|
desc = "length=%d" % len(data)
|
|
childs = OrderedDict(enumerate(data))
|
|
elif HAVE_METAARRAY and (hasattr(data, 'implements') and data.implements('MetaArray')):
|
|
childs = OrderedDict([
|
|
('data', data.view(np.ndarray)),
|
|
('meta', data.infoCopy())
|
|
])
|
|
elif isinstance(data, np.ndarray):
|
|
desc = "shape=%s dtype=%s" % (data.shape, data.dtype)
|
|
table = TableWidget()
|
|
table.setData(data)
|
|
table.setMaximumHeight(200)
|
|
widget = table
|
|
elif isinstance(data, types.TracebackType): ## convert traceback to a list of strings
|
|
frames = list(map(str.strip, traceback.format_list(traceback.extract_tb(data))))
|
|
#childs = OrderedDict([
|
|
#(i, {'file': child[0], 'line': child[1], 'function': child[2], 'code': child[3]})
|
|
#for i, child in enumerate(frames)])
|
|
#childs = OrderedDict([(i, ch) for i,ch in enumerate(frames)])
|
|
widget = QtGui.QPlainTextEdit(asUnicode('\n'.join(frames)))
|
|
widget.setMaximumHeight(200)
|
|
widget.setReadOnly(True)
|
|
else:
|
|
desc = asUnicode(data)
|
|
|
|
return typeStr, desc, childs, widget
|
|
|