fdi.utils.tree 源代码

# -*- coding: utf-8 -*-

from ..dataset.arraydataset import ArrayDataset, Column
from ..dataset.tabledataset import TableDataset
from ..dataset.datatypes import Vector
from ..dataset.metadata import Parameter
from ..dataset.attributable import Reserved_Property_Names

from itertools import chain, islice, repeat
import logging
from collections import OrderedDict
from collections.abc import MutableMapping, Sequence
from pprint import pprint
import array
import time
import io
import statistics

# create logger
logger = logging.getLogger(__name__)
# logger.debug('level %d' %  (logger.getEffectiveLevel()))


"""
Aaron Hall
https://stackoverflow.com/a/59109706
"""

SIMPLE_TYPES = [int, float, complex, str, bytes, bool, None,
                Vector]
# prefix components:
PREFIXES = {'line': (
    # space
    '    ',
    # branch
    '│   ',
    # pointers
    # tee =
    '├── ',
    # last
    '└── '
),
    'ascii': (
    # space
    '    ',
    # branch
    '|   ',
    # pointers
    # tee =
    '|__ ',
    # last
    '\__ '
), }


[文档]def tree(data_object, level=0, style='line', prefix='', seen=None): """A recursive generator, given an object object will yield a visual tree structure line by line with each line prefixed by the same characters """ # __import__('pdb').set_trace() space, branch, tee, last = PREFIXES[style] if seen is None: seen = [] elif id(data_object) in seen: return seen.append(id(data_object)) # data is a Sequence if issubclass(data_object.__class__, Sequence): contents = list((n, v) for n, v in enumerate(data_object) if not issubclass(v.__class__, SIMPLE_TYPES)) if len(contents) == 0: return else: # data is MutableMapping ot simple values contents = [] # properties # if hasattr(data_object, '__dict__'): # contents += list((n, v) for n, v in # vars(data_object).items() if # not (n.startswith('_') or n in Reserved_Property_Names # )) # state variables. Change names "_ATTR_xxx" to "xxx". Filter out Parameter if hasattr(data_object, '__getstate__'): contents += list(((n[6:] if n.startswith('_ATTR_') else n), v) for n, v in data_object.__getstate__().items() if level > 0 or not issubclass(v.__class__, Parameter)) # contents each get pointers that are ├── with a final └── : pointers = [tee] * (len(contents) - 1) + [last] for pointer, name_value in zip(pointers, contents): v = name_value[1] vc = v.__class__ shp = (' %s' % str(v.shape)) if hasattr(v, 'shape') else '' typ = '%s' % (str(v.type) if hasattr(v, 'type') else vc.__name__) # format output line ts = '<%s>%s' % (typ, shp) line = prefix + pointer + name_value[0] yield '%s%s%s' % (line, ' ' * max(1, 60-len(line)-len(ts)), ts) if issubclass(vc, (str, bytes)) or \ issubclass(vc, (ArrayDataset)) and hasattr(v, 'typecode'): pass elif issubclass(vc, (MutableMapping, Sequence)): # extend the prefix and recurse: extension = branch if pointer == tee else space # i.e. space because last, └── , above so no more | yield from tree(v, level=level, style=style, prefix=prefix+extension, seen=seen)