def baz(): z = 3 x = 725 currentDepth = currentStackDepth() # Start in this stack frame, go into the past self.assertEqual(725, getObjectByName('x')) # Start at the deepest past, and go towards the current stack frame self.assertEqual(33, getObjectByName('x', startRecent=False)) # Start at the deepest past and go deeper (before foo was defined!) self.assertEqual(None, getObjectByName('x', currentDepth)) # start at the deepest past and come towards the current stack frame self.assertEqual(33, getObjectByName('x', currentDepth, startRecent=False)) self.assertEqual('foo', getObjectName(foo))
def repr_function(function, estimatedDepth=1): f_name = getObjectName(function, estimatedDepth=estimatedDepth, ignore_names=IGNORED_NAMES) return '%s%s' % (f_name or 'λ', getFunctionCallSigs(function))
def pdir(o, indent=' ', ellipsisLimit=120, includeDocs=False, skipPrivate=True, recurseSkips=set(), recursePrettily=False, directPrint=True): """Pretty print the dir() function for Ignition things. This is designed to be used in the script console. Use it to explore objects and functions. Functions will show their call methods, with Python functions returning their defaults, if any. Attributes that are objects will be printed directly, and otherwise the type will be displayed. Disable direct print if the output of the function should be returned for use elsewhere (perhaps to a file or something). When in doubt, pdir(pdir) is a handy thing to remember. Or help(pdir), too! """ # skipTypes = set(['builtin_function_or_method', 'instancemethod', 'java.lang.Class']) skipTypes = set(['builtin_function_or_method', 'java.lang.Class']) dotdotdot = lambda s, ellipsisLimit=ellipsisLimit: s if not ellipsisLimit or len( s) <= ellipsisLimit else '%s...' % s[:ellipsisLimit - 3] out = [] name = getObjectName(o, estimatedDepth=2, ignore_names=IGNORED_NAMES) o_type = str(type(o))[7:-2] if name: out += ['%sProperties of "%s" <%s>' % (indent, name, o_type)] else: out += ['%sProperties of <%s>' % (indent, o_type)] out += ['%s%s' % (indent, '=' * len(out[0]))] obj_repr = repr(o) if obj_repr: obj_repr = obj_repr.splitlines() if '\n' in obj_repr else [obj_repr] for line in obj_repr: out += ['%s%s' % (indent, dotdotdot(line))] out += ['%s%s' % (indent, '-' * len(out[0]))] try: joinClause = '\n---\n' callExample = '%s%s' % ( indent, getFunctionCallSigs(o, joinClause), ) out += callExample.split(joinClause) out += [ '%s%s' % (indent, '-' * max([len(line) for line in callExample.split(joinClause)] + [1])) ] except: pass if getattr(o, '__doc__', ''): docstringLines = o.__doc__.strip().splitlines() if len(docstringLines) > 1: docstringLines = [docstringLines[0]] + textwrap.dedent('\n'.join( docstringLines[1:])).splitlines() maxDocLen = max([len(line) for line in docstringLines] + [1]) docPattern = '%%s%%-%ds' % maxDocLen for line in docstringLines: out += [docPattern % (indent, line)] else: out += [''] attrDir = set(dir(o)) try: if isJavaObject(o) and not skipPrivate: attributes = set(attr.name for attr in o.getDeclaredFields()) attributes |= attrDir else: raise StopIteration("Default to the normal dir command...") except: attributes = [ attribute for attribute in attrDir if not (attribute.startswith('_') and skipPrivate) ] attributes = sorted(attributes) # preprocessing maxAttrLen = max([len(attribute) for attribute in attributes] + [0]) attrTypes = [] attrTypeStrings = [] attrReprs = [] attrPrivates = [] attrDocs = [] for attribute in sorted(attributes): try: attrPrivates.append((not attribute in attrDir) or attribute.startswith('_')) if not attribute in attrDir: attrType = o.getDeclaredField(attribute).type attrTypes.append(attrType) typeStr = str(attrType)[7:-2] typeStr = typeStr.partition('$')[0] attrTypeStrings.append(typeStr) attrReprs.append(repr(getReflectedField(o, attribute))) attrDocs.append(None) else: try: if attribute in BANNED_ATTRIBUTES.get(o_type, set()): attr = BannedAttributeException('skipping %s' % attribute) attrType = "<type '<Unknown type>'> (skipped)" else: attr = getattr(o, attribute) attrType = type(attr) except Exception, error: attr = PrettyException('could not get attribute %s' % attribute) attrType = "<type '<Unknown type>'>" attrTypes.append(attrType) typeStr = str(attrType)[7:-2] typeStr = typeStr.partition('$')[0] attrTypeStrings.append(typeStr) try: if recursePrettily and isinstance( attr, PRETTY_PRINT_TYPES ) and not attribute in recurseSkips: attrReprs.append( p(attr, listLimit=10, ellipsisLimit=ellipsisLimit, nestedListLimit=4, directPrint=False)) else: if getattr(attr, '__call__', None): if re.match('(get|to|is|has)[A-Z]', attribute) and getFunctionCallSigs( attr) == '()': attrReprs.append(repr(attr())) else: attrReprs.append(repr_function(attr)) else: attrReprs.append(repr(attr)) except: try: attrReprs.append(str(attr)) except: attrReprs.append('< ? >') try: attrDocs.append(' '.join( attr.__doc__.strip().splitlines())) except: attrDocs.append(None) except AttributeError, e: try: attr = getattr(o, attribute) # print attr # print getFunctionCallSigs(attr) except: pass attrTypes.append('<--->') attrTypeStrings.append(str(e).partition(':')[0]) attrReprs.append('n/a') attrDocs.append(None) except TypeError, e: attrTypes.append('WriteOnly') attrTypeStrings.append(str(e).partition(':')[0]) attrReprs.append('n/a') attrDocs.append(None)
def p(o, indent=' ', listLimit=42, ellipsisLimit=80, nestedListLimit=10, directPrint=True): """Pretty print objects. This helps make lists, dicts, and other things easier to understand. Handy for quickly looking at datasets and lists of lists, too, since it aligns columns. """ # Pass-thru for strings if isinstance(o, (str, unicode)): return o out = [] strElePattern = '%%-%ds' numElePattern = '%%%ds' colSep = ' | ' if isinstance(o, (BasicDataset, PyDataSet)): ds = o o_name = getObjectName(o, estimatedDepth=2, ignore_names=IGNORED_NAMES) o_name = ('"%s" ' % o_name) if o_name else '' if isinstance(ds, PyDataSet): ds = ds.getUnderlyingDataset() out += [ '%s<PyDataSet> of %d elements and %d columns' % (o_name, ds.getRowCount(), ds.getColumnCount()) ] else: out += [ '%s<DataSet> of %d elements and %d columns' % (o_name, ds.getRowCount(), ds.getColumnCount()) ] out += [indent + '=' * (len(out[0]))] # preprocessing # Get the width of each column in the dataset try: data = zip(*ds.data) except AttributeError: data = [] for rix in sentinel(range(ds.getRowCount()), listLimit): data.append([ ds.getValueAt(rix, cix) for cix in range(ds.getColumnCount()) ]) colTypes = [repr(t) for t in ds.getColumnTypes()] colTypeStrs = [' <%s> ' % ct[7:-2] for ct in colTypes] colNames = [h for h in ds.getColumnNames()] colWidths = [ max([len(repr(row)) for row in col] + [len(t)] + [len(h)] + [1]) for h, t, col in zip(colNames, colTypeStrs, zip(*(data or [[0] * len(colNames)]))) ] maxRowWidth = int(math.floor(math.log10(ds.getRowCount() + 1))) prefixPattern = '%s %%%dd%s' % (indent, maxRowWidth + 1, colSep) rowPattern = prefixPattern + ' ' + colSep.join( strElePattern % colWidth if colType in ("<type 'java.lang.String'>", repr(str), repr(unicode)) else numElePattern % colWidth for colType, colWidth in zip(colTypes, colWidths)) hedPattern = indent + ' ' + ' ' * (maxRowWidth + 1) + ' ' + ' ' + colSep.join( strElePattern % colWidth for colWidth in colWidths) out += [hedPattern % tuple(colNames)] out += [hedPattern % tuple(colTypeStrs)] out += [indent + '-' * (len(out[-1]) - len(indent))] for i, row in enumerate(data): out += [rowPattern % tuple([i] + list(row))] elif isinstance(o, (list, tuple, array, ArrayList, set, frozenset, HashSet)): o_name = getObjectName(o, estimatedDepth=2, ignore_names=IGNORED_NAMES) o_type = type(o) if isinstance(o, HashSet): o = set([v for v in o]) out += [ '%s<%s> of %d elements' % (('"%s" ' % o_name) if o_name else '', '<%s> array' % o.typecode if isinstance(o, array) else str(o_type)[6:-1], len(o)) ] # preprocessing maxRowWidth = int(math.floor(math.log10(len(o) + 1))) # column alignment, if any try: colEleWidths = [ max([len(repr(r)) for r in row] + [1]) for row in zip(*o) ] except: colEleWidths = [] if not colEleWidths: colEleWidths = [ max([ len( repr(element) if not isinstance(element, PRETTY_PRINT_TYPES) else '1') for element in o ] + [1]) ] # element printing for i, element in enumerate(o): if listLimit and i >= listLimit: out += [ '%s... %d ellided (of %s total)' % (indent, len(o) - i, len(o)) ] break ixPattern = '%%%dd' if isinstance(element, (dict, set, frozenset)): ixPattern = '{%s}' % ixPattern elif isinstance(element, (list, array, ArrayList)): ixPattern = '[%s]' % ixPattern elif isinstance(element, tuple): ixPattern = '(%s)' % ixPattern elif isinstance(o, (set, frozenset)): ixPattern = ' %s?' % ixPattern else: ixPattern = ' %s ' % ixPattern prefixPattern = '%s' + ixPattern + ' %s' prefixPattern %= (indent, maxRowWidth + 1, colSep) if isinstance(element, PRETTY_PRINT_TYPES): nestedPattern = '%s' + ixPattern + ' %s%%s' nestedPattern %= (indent, maxRowWidth + 1, colSep) out += [ nestedPattern % (i, p(element, indent + ' ' * (maxRowWidth + 1 + 2 + 2 + len(colSep)), listLimit=nestedListLimit, ellipsisLimit=ellipsisLimit, nestedListLimit=nestedListLimit, directPrint=False)) ] out[-1] = out[-1][:-1] continue else: rElement = repr(element) if ellipsisLimit and len(rElement) > ellipsisLimit: if quotePattern.match(rElement): rElement = '%s...%s' % (rElement[:ellipsisLimit - 4], rElement[0]) else: rElement = '%s...' % rElement[:ellipsisLimit - 3] rowPattern = prefixPattern if isinstance(element, (str, unicode)): rowPattern += ' ' + strElePattern % colEleWidths[0] else: rowPattern += ' ' + numElePattern % colEleWidths[0] out += [rowPattern % (i, rElement)] elif isinstance(o, (dict, HashMap)): o_name = getObjectName(o, estimatedDepth=2, ignore_names=IGNORED_NAMES) o_type = type(o) if isinstance(o, HashMap): o = dict([(str(key), o.get(key)) for key in sorted(o.keySet())]) out.append( '%s<%s> of %d elements' % (('"%s" ' % o_name) if o_name else '', str(o_type)[6:-1], len(o))) # preprocessing maxKeyWidth = max([len(repr(key)) for key in o.keys()] + [1]) maxValWidth = max([ len(repr(val) if not isinstance(val, PRETTY_PRINT_TYPES) else '1') for val in o.values() ] + [1]) elementPattern = '%s%%%ds : %%-%ds' % (indent, maxKeyWidth, maxValWidth) # element printing for i, key in enumerate(sorted(o.keys())): if listLimit and i >= listLimit: out += [ '%s... %d ellided (of %s total)' % (indent, len(o) - i, len(o)) ] break element = o[key] if isinstance(element, PRETTY_PRINT_TYPES ) and element is not o: #don't recurse here! nestedPattern = '%s%%%ds : %%s' % (indent, maxKeyWidth) out += [ nestedPattern % (key, p(element, indent + ' ' * (maxKeyWidth + 3), listLimit=nestedListLimit, ellipsisLimit=ellipsisLimit, nestedListLimit=nestedListLimit, directPrint=False).lstrip()) ] out[-1] = out[-1][:-1] continue rElement = repr(element) if ellipsisLimit and len(rElement) > ellipsisLimit: if quotePattern.match(rElement): rElement = '%s...%s' % (rElement[:ellipsisLimit - 4], rElement[0]) else: rElement = '%s...' % rElement[:ellipsisLimit - 3] out += [elementPattern % (key, rElement)] elif isinstance(o, FrameType): out += [ '<frame in "%s" of "%s" on line %d%s>' % (o.f_code.co_filename, o.f_code.co_name, o.f_lineno, ('(tracing with %s)' % o.f_trace) if o.f_trace else '') ] elif isinstance(o, (FunctionType, LambdaType)): out += [repr_function(o, estimatedDepth=1)] else: if not isinstance(o, GeneratorType): try: # if it's some sort of unknown iterable if directPrint: print '(Unrecognized type - iteration attempted for type <%r>)' % str( type(o))[6:-1] try: p(dict((k, o.get(k)) for k in o), indent, listLimit, ellipsisLimit, nestedListLimit, directPrint) except: p([v for v in o], indent, listLimit, ellipsisLimit, nestedListLimit, directPrint) return else: output = '\n(Unrecognized type - iteration attempted for type <%r>)' % str( type(o))[6:-1] try: output += p(dict((k, o.get(k)) for k in o), indent, listLimit, ellipsisLimit, nestedListLimit, directPrint) except: output += p([v for v in o], indent, listLimit, ellipsisLimit, nestedListLimit, directPrint) return output except Exception, error: out += [repr(o)] else: