]> git.wh0rd.org - home.git/blob - .ipython/profile_default/startup/50-dump.py
e1910eae62059286bf136ff198338a8db967d73f
[home.git] / .ipython / profile_default / startup / 50-dump.py
1 #!/usr/bin/python
2 # Released into the public domain.
3 # Written by Mike Frysinger <vapier>.
4
5 """Module for diving into python objects."""
6
7 from __future__ import print_function
8
9
10 class Dump(object):
11
12 try:
13 from cStringIO import StringIO
14 except:
15 from io import StringIO
16 import datetime
17 import logging
18 import pydoc
19 import os
20 import sys
21 import types
22
23 MAX_DEPTH = 1
24
25 # Objects that hold multiple objects (can be looped over).
26 TYPES_ITERABLES = (
27 types.GeneratorType,
28 types.ListType,
29 types.TupleType,
30 )
31
32 # Objects that we shouldn't really probe.
33 TYPES_CALLABLE = (
34 types.FunctionType,
35 types.LambdaType,
36 )
37
38 # Simple objects we don't decode further.
39 TYPES_SCALAR = (
40 types.BooleanType,
41 types.ComplexType,
42 types.FloatType,
43 types.IntType,
44 types.LongType,
45 types.NoneType,
46 types.StringType,
47 types.UnicodeType,
48
49 types.ClassType,
50 types.TypeType,
51 )
52
53 # Objects that are dictionary based.
54 TYPES_DICT = (
55 types.DictType,
56 types.DictionaryType,
57 )
58
59 # Standard python objects we don't normally expand.
60 TYPES_STANDARD = (
61 datetime.date,
62 datetime.datetime,
63 datetime.time,
64 logging.Logger
65 )
66
67 # Color logic.
68 _C = lambda x: '\033[%im' % x
69 def C(self, m, c):
70 return '%s%s%s' % (c, m, self.NORMAL)
71 NORMAL = _C(0)
72 BOLD = _C(1)
73 UNDERLINE = _C(4)
74 #BLACK = _C()
75
76 PURPLE = _C(95)
77 CYAN = _C(96)
78 DARKCYAN = _C(36)
79 BLUE = _C(94)
80 GREEN = _C(92)
81 YELLOW = _C(93)
82 RED = _C(91)
83
84 def __init__(self, obj, depth=None, out=None, linelim=150,
85 show_internal=False, show_all=False, show_std=False):
86 if out is None:
87 out = self.StringIO()
88 #out = self.sys.stdout
89 self.out = out
90
91 self.depth = depth if depth else self.MAX_DEPTH
92 self.line_limit = linelim
93 self.show_internal = show_internal
94 self.show_all = show_all
95 self.show_std = show_std
96
97 self.seen = set()
98 self.dump(obj)
99
100 if hasattr(out, 'getvalue'):
101 self.pydoc.pager(out.getvalue())
102
103 return None
104
105 def trunc(self, s):
106 """Truncate |s| length to self.line_limit bytes"""
107 if len(s) > self.line_limit:
108 s = '%s %s' % (s[0:self.line_limit],
109 self.C('<truncated>', self.RED))
110 return s
111
112 def dump(self, obj, depth=0, name=None):
113 """Dump |obj| with |name|"""
114 indent = ' ' * depth
115 def w(msg, indent=indent, color=None):
116 for line in msg.splitlines():
117 if color:
118 line = self.C(line, color)
119 self.out.write('%s%s\n' % (indent, line))
120 def d(obj, **kwargs):
121 try:
122 self.dump(obj, depth=depth + 1, **kwargs)
123 except Exception as e:
124 w(' <error probing>: %s' % (e,), color=self.RED)
125 raise
126
127 if ((not self.show_std and isinstance(obj, self.TYPES_STANDARD)) or
128 isinstance(obj, self.TYPES_SCALAR)):
129 w('%s: %s' % (self.C(name, self.BOLD), obj), indent=indent[:-2])
130 return
131
132 try:
133 if obj in self.seen:
134 w('%s: %s' % (self.C(name, self.BOLD),
135 self.C('<loop>', self.RED)), indent=indent[:-2])
136 return
137 self.seen.add(obj)
138 except TypeError:
139 pass
140
141 if name:
142 w('%s' % (name,), color=self.BOLD, indent=indent[:-2])
143
144 objr = repr(obj)
145 objs = str(obj)
146 if objr == objs:
147 w('%s: %s' % (type(obj), self.trunc(objs),))
148 else:
149 w('Object.type: %s' % (type(obj),))
150 w(' .repr: %s' % (self.trunc(objr),))
151 w(' .str : %s' % (self.trunc(objs),))
152
153 if depth > self.depth:
154 w('<stop; depth limit hit at %i>' % (depth,), color=self.RED)
155 return
156
157 if isinstance(obj, self.TYPES_ITERABLES):
158 # Iterable types.
159 for i, o in enumerate(obj):
160 d(o, name='[%i]' % (i,))
161 elif isinstance(obj, self.TYPES_SCALAR):
162 # Scalar types; already shown above.
163 pass
164 elif isinstance(obj, self.TYPES_DICT):
165 # Dictionary types.
166 for k, v in obj.items():
167 d(v, name='{%r}' % (k,))
168 elif isinstance(obj, self.TYPES_STANDARD):
169 # Standard types; already shown above.
170 pass
171 elif isinstance(obj, self.TYPES_CALLABLE):
172 # Callable functions.
173 doc = getattr(obj, 'func_doc', None)
174 if doc:
175 w('"""%s"""' % (doc.strip(),), indent=indent + ' ',
176 color=self.BLUE)
177 else:
178 # Unknown type; probe it!
179 doc = getattr(obj, '__doc__', None)
180 if doc:
181 w('"""%s"""' % (doc.strip(),), indent=indent + ' ',
182 color=self.BLUE)
183
184 for k, v in getattr(obj, '__dict__', {}).items():
185 d(v, name='{%r}' % (k,))
186
187 for k in dir(obj):
188 try:
189 s = self.trunc(repr(getattr(obj, k)))
190 except Exception as e:
191 w(' %s: %s' % (self.C(k, self.BOLD),
192 self.C('<error> %s' % str(e), self.RED)))
193 continue
194
195 if k.startswith('__'):
196 if self.show_all or not k.endswith('__'):
197 w(' %s (skipping): %s' % (self.C(k, self.BOLD), s))
198 elif self.show_internal or not k.startswith('_'):
199 d(getattr(obj, k), name=k)
200
201
202 def dump(*args, **kwargs):
203 d = Dump(*args, **kwargs)
204 del d