From: Mike Frysinger Date: Sat, 4 Apr 2015 19:14:35 +0000 (-0400) Subject: ipython: add a dumper helper X-Git-Url: https://git.wh0rd.org/?p=home.git;a=commitdiff_plain;h=c4372a0b1fa455920343bdc9124f69742214e9eb ipython: add a dumper helper --- diff --git a/.ipython/profile_default/startup/50-dump.py b/.ipython/profile_default/startup/50-dump.py new file mode 100644 index 0000000..565c544 --- /dev/null +++ b/.ipython/profile_default/startup/50-dump.py @@ -0,0 +1,201 @@ +#!/usr/bin/python +# Released into the public domain. +# Written by Mike Frysinger . + +"""Module for diving into python objects.""" + +from __future__ import print_function + + +class Dump(object): + + import cStringIO + import datetime + import logging + import pydoc + import os + import sys + import types + + MAX_DEPTH = 1 + + # Objects that hold multiple objects (can be looped over). + TYPES_ITERABLES = ( + types.GeneratorType, + types.ListType, + types.TupleType, + ) + + # Objects that we shouldn't really probe. + TYPES_CALLABLE = ( + types.FunctionType, + types.LambdaType, + ) + + # Simple objects we don't decode further. + TYPES_SCALAR = ( + types.BooleanType, + types.ComplexType, + types.FloatType, + types.IntType, + types.LongType, + types.NoneType, + types.StringType, + types.UnicodeType, + + types.ClassType, + types.TypeType, + ) + + # Objects that are dictionary based. + TYPES_DICT = ( + types.DictType, + types.DictionaryType, + ) + + # Standard python objects we don't normally expand. + TYPES_STANDARD = ( + datetime.date, + datetime.datetime, + datetime.time, + logging.Logger + ) + + # Color logic. + _C = lambda x: '\033[%im' % x + def C(self, m, c): + return '%s%s%s' % (c, m, self.NORMAL) + NORMAL = _C(0) + BOLD = _C(1) + UNDERLINE = _C(4) + #BLACK = _C() + + PURPLE = _C(95) + CYAN = _C(96) + DARKCYAN = _C(36) + BLUE = _C(94) + GREEN = _C(92) + YELLOW = _C(93) + RED = _C(91) + + def __init__(self, obj, depth=None, out=None, linelim=150, + show_internal=False, show_all=False, show_std=False): + if out is None: + out = self.cStringIO.StringIO() + #out = self.sys.stdout + self.out = out + + self.depth = depth if depth else self.MAX_DEPTH + self.line_limit = linelim + self.show_internal = show_internal + self.show_all = show_all + self.show_std = show_std + + self.seen = set() + self.dump(obj) + + if hasattr(out, 'getvalue'): + self.pydoc.pager(out.getvalue()) + + return None + + def trunc(self, s): + """Truncate |s| length to self.line_limit bytes""" + if len(s) > self.line_limit: + s = '%s %s' % (s[0:self.line_limit], + self.C('', self.RED)) + return s + + def dump(self, obj, depth=0, name=None): + """Dump |obj| with |name|""" + indent = ' ' * depth + def w(msg, indent=indent, color=None): + for line in msg.splitlines(): + if color: + line = self.C(line, color) + self.out.write('%s%s\n' % (indent, line)) + def d(obj, **kwargs): + try: + self.dump(obj, depth=depth + 1, **kwargs) + except Exception as e: + w(' : %s' % (e,), color=self.RED) + raise + + if ((not self.show_std and isinstance(obj, self.TYPES_STANDARD)) or + isinstance(obj, self.TYPES_SCALAR)): + w('%s: %s' % (self.C(name, self.BOLD), obj), indent=indent[:-2]) + return + + try: + if obj in self.seen: + w('%s: %s' % (self.C(name, self.BOLD), + self.C('', self.RED)), indent=indent[:-2]) + return + self.seen.add(obj) + except TypeError: + pass + + if name: + w('%s' % (name,), color=self.BOLD, indent=indent[:-2]) + + objr = repr(obj) + objs = str(obj) + if objr == objs: + w('%s: %s' % (type(obj), self.trunc(objs),)) + else: + w('Object.type: %s' % (type(obj),)) + w(' .repr: %s' % (self.trunc(objr),)) + w(' .str : %s' % (self.trunc(objs),)) + + if depth > self.depth: + w('' % (depth,), color=self.RED) + return + + if isinstance(obj, self.TYPES_ITERABLES): + # Iterable types. + for i, o in enumerate(obj): + d(o, name='[%i]' % (i,)) + elif isinstance(obj, self.TYPES_SCALAR): + # Scalar types; already shown above. + pass + elif isinstance(obj, self.TYPES_DICT): + # Dictionary types. + for k, v in obj.items(): + d(v, name='{%r}' % (k,)) + elif isinstance(obj, self.TYPES_STANDARD): + # Standard types; already shown above. + pass + elif isinstance(obj, self.TYPES_CALLABLE): + # Callable functions. + doc = getattr(obj, 'func_doc', None) + if doc: + w('"""%s"""' % (doc.strip(),), indent=indent + ' ', + color=self.BLUE) + else: + # Unknown type; probe it! + doc = getattr(obj, '__doc__', None) + if doc: + w('"""%s"""' % (doc.strip(),), indent=indent + ' ', + color=self.BLUE) + + for k, v in getattr(obj, '__dict__', {}).items(): + d(v, name='{%r}' % (k,)) + + for k in dir(obj): + try: + s = self.trunc(repr(getattr(obj, k))) + except Exception as e: + w(' %s: %s' % (self.C(k, self.BOLD), + self.C(' %s' % str(e), self.RED))) + continue + + if k.startswith('__'): + if self.show_all or not k.endswith('__'): + w(' %s (skipping): %s' % (self.C(k, self.BOLD), s)) + elif self.show_internal or not k.startswith('_'): + d(getattr(obj, k), name=k) + + +def dump(*args, **kwargs): + d = Dump(*args, **kwargs) + del d