##// END OF EJS Templates
Merge pull request #4405 from takluyver/builtin-types-pprint-py3...
Min RK -
r13142:25ad487b merge
parent child Browse files
Show More
@@ -1,790 +1,789 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Python advanced pretty printer. This pretty printer is intended to
3 Python advanced pretty printer. This pretty printer is intended to
4 replace the old `pprint` python module which does not allow developers
4 replace the old `pprint` python module which does not allow developers
5 to provide their own pretty print callbacks.
5 to provide their own pretty print callbacks.
6
6
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8
8
9
9
10 Example Usage
10 Example Usage
11 -------------
11 -------------
12
12
13 To directly print the representation of an object use `pprint`::
13 To directly print the representation of an object use `pprint`::
14
14
15 from pretty import pprint
15 from pretty import pprint
16 pprint(complex_object)
16 pprint(complex_object)
17
17
18 To get a string of the output use `pretty`::
18 To get a string of the output use `pretty`::
19
19
20 from pretty import pretty
20 from pretty import pretty
21 string = pretty(complex_object)
21 string = pretty(complex_object)
22
22
23
23
24 Extending
24 Extending
25 ---------
25 ---------
26
26
27 The pretty library allows developers to add pretty printing rules for their
27 The pretty library allows developers to add pretty printing rules for their
28 own objects. This process is straightforward. All you have to do is to
28 own objects. This process is straightforward. All you have to do is to
29 add a `_repr_pretty_` method to your object and call the methods on the
29 add a `_repr_pretty_` method to your object and call the methods on the
30 pretty printer passed::
30 pretty printer passed::
31
31
32 class MyObject(object):
32 class MyObject(object):
33
33
34 def _repr_pretty_(self, p, cycle):
34 def _repr_pretty_(self, p, cycle):
35 ...
35 ...
36
36
37 Depending on the python version you want to support you have two
37 Depending on the python version you want to support you have two
38 possibilities. The following list shows the python 2.5 version and the
38 possibilities. The following list shows the python 2.5 version and the
39 compatibility one.
39 compatibility one.
40
40
41
41
42 Here the example implementation of a `_repr_pretty_` method for a list
42 Here the example implementation of a `_repr_pretty_` method for a list
43 subclass for python 2.5 and higher (python 2.5 requires the with statement
43 subclass for python 2.5 and higher (python 2.5 requires the with statement
44 __future__ import)::
44 __future__ import)::
45
45
46 class MyList(list):
46 class MyList(list):
47
47
48 def _repr_pretty_(self, p, cycle):
48 def _repr_pretty_(self, p, cycle):
49 if cycle:
49 if cycle:
50 p.text('MyList(...)')
50 p.text('MyList(...)')
51 else:
51 else:
52 with p.group(8, 'MyList([', '])'):
52 with p.group(8, 'MyList([', '])'):
53 for idx, item in enumerate(self):
53 for idx, item in enumerate(self):
54 if idx:
54 if idx:
55 p.text(',')
55 p.text(',')
56 p.breakable()
56 p.breakable()
57 p.pretty(item)
57 p.pretty(item)
58
58
59 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
59 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
60 react to that or the result is an infinite loop. `p.text()` just adds
60 react to that or the result is an infinite loop. `p.text()` just adds
61 non breaking text to the output, `p.breakable()` either adds a whitespace
61 non breaking text to the output, `p.breakable()` either adds a whitespace
62 or breaks here. If you pass it an argument it's used instead of the
62 or breaks here. If you pass it an argument it's used instead of the
63 default space. `p.pretty` prettyprints another object using the pretty print
63 default space. `p.pretty` prettyprints another object using the pretty print
64 method.
64 method.
65
65
66 The first parameter to the `group` function specifies the extra indentation
66 The first parameter to the `group` function specifies the extra indentation
67 of the next line. In this example the next item will either be not
67 of the next line. In this example the next item will either be not
68 breaked (if the items are short enough) or aligned with the right edge of
68 breaked (if the items are short enough) or aligned with the right edge of
69 the opening bracked of `MyList`.
69 the opening bracked of `MyList`.
70
70
71 If you want to support python 2.4 and lower you can use this code::
71 If you want to support python 2.4 and lower you can use this code::
72
72
73 class MyList(list):
73 class MyList(list):
74
74
75 def _repr_pretty_(self, p, cycle):
75 def _repr_pretty_(self, p, cycle):
76 if cycle:
76 if cycle:
77 p.text('MyList(...)')
77 p.text('MyList(...)')
78 else:
78 else:
79 p.begin_group(8, 'MyList([')
79 p.begin_group(8, 'MyList([')
80 for idx, item in enumerate(self):
80 for idx, item in enumerate(self):
81 if idx:
81 if idx:
82 p.text(',')
82 p.text(',')
83 p.breakable()
83 p.breakable()
84 p.pretty(item)
84 p.pretty(item)
85 p.end_group(8, '])')
85 p.end_group(8, '])')
86
86
87 If you just want to indent something you can use the group function
87 If you just want to indent something you can use the group function
88 without open / close parameters. Under python 2.5 you can also use this
88 without open / close parameters. Under python 2.5 you can also use this
89 code::
89 code::
90
90
91 with p.indent(2):
91 with p.indent(2):
92 ...
92 ...
93
93
94 Or under python2.4 you might want to modify ``p.indentation`` by hand but
94 Or under python2.4 you might want to modify ``p.indentation`` by hand but
95 this is rather ugly.
95 this is rather ugly.
96
96
97 Inheritance diagram:
97 Inheritance diagram:
98
98
99 .. inheritance-diagram:: IPython.lib.pretty
99 .. inheritance-diagram:: IPython.lib.pretty
100 :parts: 3
100 :parts: 3
101
101
102 :copyright: 2007 by Armin Ronacher.
102 :copyright: 2007 by Armin Ronacher.
103 Portions (c) 2009 by Robert Kern.
103 Portions (c) 2009 by Robert Kern.
104 :license: BSD License.
104 :license: BSD License.
105 """
105 """
106 from __future__ import with_statement
107 from contextlib import contextmanager
106 from contextlib import contextmanager
108 import sys
107 import sys
109 import types
108 import types
110 import re
109 import re
111 import datetime
110 import datetime
112 from StringIO import StringIO
111 from StringIO import StringIO
113 from collections import deque
112 from collections import deque
114
113
115
114
116 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
115 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
117 'for_type', 'for_type_by_name']
116 'for_type', 'for_type_by_name']
118
117
119
118
120 _re_pattern_type = type(re.compile(''))
119 _re_pattern_type = type(re.compile(''))
121
120
122
121
123 def pretty(obj, verbose=False, max_width=79, newline='\n'):
122 def pretty(obj, verbose=False, max_width=79, newline='\n'):
124 """
123 """
125 Pretty print the object's representation.
124 Pretty print the object's representation.
126 """
125 """
127 stream = StringIO()
126 stream = StringIO()
128 printer = RepresentationPrinter(stream, verbose, max_width, newline)
127 printer = RepresentationPrinter(stream, verbose, max_width, newline)
129 printer.pretty(obj)
128 printer.pretty(obj)
130 printer.flush()
129 printer.flush()
131 return stream.getvalue()
130 return stream.getvalue()
132
131
133
132
134 def pprint(obj, verbose=False, max_width=79, newline='\n'):
133 def pprint(obj, verbose=False, max_width=79, newline='\n'):
135 """
134 """
136 Like `pretty` but print to stdout.
135 Like `pretty` but print to stdout.
137 """
136 """
138 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
137 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
139 printer.pretty(obj)
138 printer.pretty(obj)
140 printer.flush()
139 printer.flush()
141 sys.stdout.write(newline)
140 sys.stdout.write(newline)
142 sys.stdout.flush()
141 sys.stdout.flush()
143
142
144 class _PrettyPrinterBase(object):
143 class _PrettyPrinterBase(object):
145
144
146 @contextmanager
145 @contextmanager
147 def indent(self, indent):
146 def indent(self, indent):
148 """with statement support for indenting/dedenting."""
147 """with statement support for indenting/dedenting."""
149 self.indentation += indent
148 self.indentation += indent
150 try:
149 try:
151 yield
150 yield
152 finally:
151 finally:
153 self.indentation -= indent
152 self.indentation -= indent
154
153
155 @contextmanager
154 @contextmanager
156 def group(self, indent=0, open='', close=''):
155 def group(self, indent=0, open='', close=''):
157 """like begin_group / end_group but for the with statement."""
156 """like begin_group / end_group but for the with statement."""
158 self.begin_group(indent, open)
157 self.begin_group(indent, open)
159 try:
158 try:
160 yield
159 yield
161 finally:
160 finally:
162 self.end_group(indent, close)
161 self.end_group(indent, close)
163
162
164 class PrettyPrinter(_PrettyPrinterBase):
163 class PrettyPrinter(_PrettyPrinterBase):
165 """
164 """
166 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
165 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
167 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
166 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
168 this printer knows nothing about the default pprinters or the `_repr_pretty_`
167 this printer knows nothing about the default pprinters or the `_repr_pretty_`
169 callback method.
168 callback method.
170 """
169 """
171
170
172 def __init__(self, output, max_width=79, newline='\n'):
171 def __init__(self, output, max_width=79, newline='\n'):
173 self.output = output
172 self.output = output
174 self.max_width = max_width
173 self.max_width = max_width
175 self.newline = newline
174 self.newline = newline
176 self.output_width = 0
175 self.output_width = 0
177 self.buffer_width = 0
176 self.buffer_width = 0
178 self.buffer = deque()
177 self.buffer = deque()
179
178
180 root_group = Group(0)
179 root_group = Group(0)
181 self.group_stack = [root_group]
180 self.group_stack = [root_group]
182 self.group_queue = GroupQueue(root_group)
181 self.group_queue = GroupQueue(root_group)
183 self.indentation = 0
182 self.indentation = 0
184
183
185 def _break_outer_groups(self):
184 def _break_outer_groups(self):
186 while self.max_width < self.output_width + self.buffer_width:
185 while self.max_width < self.output_width + self.buffer_width:
187 group = self.group_queue.deq()
186 group = self.group_queue.deq()
188 if not group:
187 if not group:
189 return
188 return
190 while group.breakables:
189 while group.breakables:
191 x = self.buffer.popleft()
190 x = self.buffer.popleft()
192 self.output_width = x.output(self.output, self.output_width)
191 self.output_width = x.output(self.output, self.output_width)
193 self.buffer_width -= x.width
192 self.buffer_width -= x.width
194 while self.buffer and isinstance(self.buffer[0], Text):
193 while self.buffer and isinstance(self.buffer[0], Text):
195 x = self.buffer.popleft()
194 x = self.buffer.popleft()
196 self.output_width = x.output(self.output, self.output_width)
195 self.output_width = x.output(self.output, self.output_width)
197 self.buffer_width -= x.width
196 self.buffer_width -= x.width
198
197
199 def text(self, obj):
198 def text(self, obj):
200 """Add literal text to the output."""
199 """Add literal text to the output."""
201 width = len(obj)
200 width = len(obj)
202 if self.buffer:
201 if self.buffer:
203 text = self.buffer[-1]
202 text = self.buffer[-1]
204 if not isinstance(text, Text):
203 if not isinstance(text, Text):
205 text = Text()
204 text = Text()
206 self.buffer.append(text)
205 self.buffer.append(text)
207 text.add(obj, width)
206 text.add(obj, width)
208 self.buffer_width += width
207 self.buffer_width += width
209 self._break_outer_groups()
208 self._break_outer_groups()
210 else:
209 else:
211 self.output.write(obj)
210 self.output.write(obj)
212 self.output_width += width
211 self.output_width += width
213
212
214 def breakable(self, sep=' '):
213 def breakable(self, sep=' '):
215 """
214 """
216 Add a breakable separator to the output. This does not mean that it
215 Add a breakable separator to the output. This does not mean that it
217 will automatically break here. If no breaking on this position takes
216 will automatically break here. If no breaking on this position takes
218 place the `sep` is inserted which default to one space.
217 place the `sep` is inserted which default to one space.
219 """
218 """
220 width = len(sep)
219 width = len(sep)
221 group = self.group_stack[-1]
220 group = self.group_stack[-1]
222 if group.want_break:
221 if group.want_break:
223 self.flush()
222 self.flush()
224 self.output.write(self.newline)
223 self.output.write(self.newline)
225 self.output.write(' ' * self.indentation)
224 self.output.write(' ' * self.indentation)
226 self.output_width = self.indentation
225 self.output_width = self.indentation
227 self.buffer_width = 0
226 self.buffer_width = 0
228 else:
227 else:
229 self.buffer.append(Breakable(sep, width, self))
228 self.buffer.append(Breakable(sep, width, self))
230 self.buffer_width += width
229 self.buffer_width += width
231 self._break_outer_groups()
230 self._break_outer_groups()
232
231
233 def break_(self):
232 def break_(self):
234 """
233 """
235 Explicitly insert a newline into the output, maintaining correct indentation.
234 Explicitly insert a newline into the output, maintaining correct indentation.
236 """
235 """
237 self.flush()
236 self.flush()
238 self.output.write(self.newline)
237 self.output.write(self.newline)
239 self.output.write(' ' * self.indentation)
238 self.output.write(' ' * self.indentation)
240 self.output_width = self.indentation
239 self.output_width = self.indentation
241 self.buffer_width = 0
240 self.buffer_width = 0
242
241
243
242
244 def begin_group(self, indent=0, open=''):
243 def begin_group(self, indent=0, open=''):
245 """
244 """
246 Begin a group. If you want support for python < 2.5 which doesn't has
245 Begin a group. If you want support for python < 2.5 which doesn't has
247 the with statement this is the preferred way:
246 the with statement this is the preferred way:
248
247
249 p.begin_group(1, '{')
248 p.begin_group(1, '{')
250 ...
249 ...
251 p.end_group(1, '}')
250 p.end_group(1, '}')
252
251
253 The python 2.5 expression would be this:
252 The python 2.5 expression would be this:
254
253
255 with p.group(1, '{', '}'):
254 with p.group(1, '{', '}'):
256 ...
255 ...
257
256
258 The first parameter specifies the indentation for the next line (usually
257 The first parameter specifies the indentation for the next line (usually
259 the width of the opening text), the second the opening text. All
258 the width of the opening text), the second the opening text. All
260 parameters are optional.
259 parameters are optional.
261 """
260 """
262 if open:
261 if open:
263 self.text(open)
262 self.text(open)
264 group = Group(self.group_stack[-1].depth + 1)
263 group = Group(self.group_stack[-1].depth + 1)
265 self.group_stack.append(group)
264 self.group_stack.append(group)
266 self.group_queue.enq(group)
265 self.group_queue.enq(group)
267 self.indentation += indent
266 self.indentation += indent
268
267
269 def end_group(self, dedent=0, close=''):
268 def end_group(self, dedent=0, close=''):
270 """End a group. See `begin_group` for more details."""
269 """End a group. See `begin_group` for more details."""
271 self.indentation -= dedent
270 self.indentation -= dedent
272 group = self.group_stack.pop()
271 group = self.group_stack.pop()
273 if not group.breakables:
272 if not group.breakables:
274 self.group_queue.remove(group)
273 self.group_queue.remove(group)
275 if close:
274 if close:
276 self.text(close)
275 self.text(close)
277
276
278 def flush(self):
277 def flush(self):
279 """Flush data that is left in the buffer."""
278 """Flush data that is left in the buffer."""
280 for data in self.buffer:
279 for data in self.buffer:
281 self.output_width += data.output(self.output, self.output_width)
280 self.output_width += data.output(self.output, self.output_width)
282 self.buffer.clear()
281 self.buffer.clear()
283 self.buffer_width = 0
282 self.buffer_width = 0
284
283
285
284
286 def _get_mro(obj_class):
285 def _get_mro(obj_class):
287 """ Get a reasonable method resolution order of a class and its superclasses
286 """ Get a reasonable method resolution order of a class and its superclasses
288 for both old-style and new-style classes.
287 for both old-style and new-style classes.
289 """
288 """
290 if not hasattr(obj_class, '__mro__'):
289 if not hasattr(obj_class, '__mro__'):
291 # Old-style class. Mix in object to make a fake new-style class.
290 # Old-style class. Mix in object to make a fake new-style class.
292 try:
291 try:
293 obj_class = type(obj_class.__name__, (obj_class, object), {})
292 obj_class = type(obj_class.__name__, (obj_class, object), {})
294 except TypeError:
293 except TypeError:
295 # Old-style extension type that does not descend from object.
294 # Old-style extension type that does not descend from object.
296 # FIXME: try to construct a more thorough MRO.
295 # FIXME: try to construct a more thorough MRO.
297 mro = [obj_class]
296 mro = [obj_class]
298 else:
297 else:
299 mro = obj_class.__mro__[1:-1]
298 mro = obj_class.__mro__[1:-1]
300 else:
299 else:
301 mro = obj_class.__mro__
300 mro = obj_class.__mro__
302 return mro
301 return mro
303
302
304
303
305 class RepresentationPrinter(PrettyPrinter):
304 class RepresentationPrinter(PrettyPrinter):
306 """
305 """
307 Special pretty printer that has a `pretty` method that calls the pretty
306 Special pretty printer that has a `pretty` method that calls the pretty
308 printer for a python object.
307 printer for a python object.
309
308
310 This class stores processing data on `self` so you must *never* use
309 This class stores processing data on `self` so you must *never* use
311 this class in a threaded environment. Always lock it or reinstanciate
310 this class in a threaded environment. Always lock it or reinstanciate
312 it.
311 it.
313
312
314 Instances also have a verbose flag callbacks can access to control their
313 Instances also have a verbose flag callbacks can access to control their
315 output. For example the default instance repr prints all attributes and
314 output. For example the default instance repr prints all attributes and
316 methods that are not prefixed by an underscore if the printer is in
315 methods that are not prefixed by an underscore if the printer is in
317 verbose mode.
316 verbose mode.
318 """
317 """
319
318
320 def __init__(self, output, verbose=False, max_width=79, newline='\n',
319 def __init__(self, output, verbose=False, max_width=79, newline='\n',
321 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
320 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
322
321
323 PrettyPrinter.__init__(self, output, max_width, newline)
322 PrettyPrinter.__init__(self, output, max_width, newline)
324 self.verbose = verbose
323 self.verbose = verbose
325 self.stack = []
324 self.stack = []
326 if singleton_pprinters is None:
325 if singleton_pprinters is None:
327 singleton_pprinters = _singleton_pprinters.copy()
326 singleton_pprinters = _singleton_pprinters.copy()
328 self.singleton_pprinters = singleton_pprinters
327 self.singleton_pprinters = singleton_pprinters
329 if type_pprinters is None:
328 if type_pprinters is None:
330 type_pprinters = _type_pprinters.copy()
329 type_pprinters = _type_pprinters.copy()
331 self.type_pprinters = type_pprinters
330 self.type_pprinters = type_pprinters
332 if deferred_pprinters is None:
331 if deferred_pprinters is None:
333 deferred_pprinters = _deferred_type_pprinters.copy()
332 deferred_pprinters = _deferred_type_pprinters.copy()
334 self.deferred_pprinters = deferred_pprinters
333 self.deferred_pprinters = deferred_pprinters
335
334
336 def pretty(self, obj):
335 def pretty(self, obj):
337 """Pretty print the given object."""
336 """Pretty print the given object."""
338 obj_id = id(obj)
337 obj_id = id(obj)
339 cycle = obj_id in self.stack
338 cycle = obj_id in self.stack
340 self.stack.append(obj_id)
339 self.stack.append(obj_id)
341 self.begin_group()
340 self.begin_group()
342 try:
341 try:
343 obj_class = getattr(obj, '__class__', None) or type(obj)
342 obj_class = getattr(obj, '__class__', None) or type(obj)
344 # First try to find registered singleton printers for the type.
343 # First try to find registered singleton printers for the type.
345 try:
344 try:
346 printer = self.singleton_pprinters[obj_id]
345 printer = self.singleton_pprinters[obj_id]
347 except (TypeError, KeyError):
346 except (TypeError, KeyError):
348 pass
347 pass
349 else:
348 else:
350 return printer(obj, self, cycle)
349 return printer(obj, self, cycle)
351 # Next walk the mro and check for either:
350 # Next walk the mro and check for either:
352 # 1) a registered printer
351 # 1) a registered printer
353 # 2) a _repr_pretty_ method
352 # 2) a _repr_pretty_ method
354 for cls in _get_mro(obj_class):
353 for cls in _get_mro(obj_class):
355 if cls in self.type_pprinters:
354 if cls in self.type_pprinters:
356 # printer registered in self.type_pprinters
355 # printer registered in self.type_pprinters
357 return self.type_pprinters[cls](obj, self, cycle)
356 return self.type_pprinters[cls](obj, self, cycle)
358 else:
357 else:
359 # deferred printer
358 # deferred printer
360 printer = self._in_deferred_types(cls)
359 printer = self._in_deferred_types(cls)
361 if printer is not None:
360 if printer is not None:
362 return printer(obj, self, cycle)
361 return printer(obj, self, cycle)
363 else:
362 else:
364 # Finally look for special method names.
363 # Finally look for special method names.
365 # Some objects automatically create any requested
364 # Some objects automatically create any requested
366 # attribute. Try to ignore most of them by checking for
365 # attribute. Try to ignore most of them by checking for
367 # callability.
366 # callability.
368 if '_repr_pretty_' in cls.__dict__:
367 if '_repr_pretty_' in cls.__dict__:
369 meth = cls._repr_pretty_
368 meth = cls._repr_pretty_
370 if callable(meth):
369 if callable(meth):
371 return meth(obj, self, cycle)
370 return meth(obj, self, cycle)
372 return _default_pprint(obj, self, cycle)
371 return _default_pprint(obj, self, cycle)
373 finally:
372 finally:
374 self.end_group()
373 self.end_group()
375 self.stack.pop()
374 self.stack.pop()
376
375
377 def _in_deferred_types(self, cls):
376 def _in_deferred_types(self, cls):
378 """
377 """
379 Check if the given class is specified in the deferred type registry.
378 Check if the given class is specified in the deferred type registry.
380
379
381 Returns the printer from the registry if it exists, and None if the
380 Returns the printer from the registry if it exists, and None if the
382 class is not in the registry. Successful matches will be moved to the
381 class is not in the registry. Successful matches will be moved to the
383 regular type registry for future use.
382 regular type registry for future use.
384 """
383 """
385 mod = getattr(cls, '__module__', None)
384 mod = getattr(cls, '__module__', None)
386 name = getattr(cls, '__name__', None)
385 name = getattr(cls, '__name__', None)
387 key = (mod, name)
386 key = (mod, name)
388 printer = None
387 printer = None
389 if key in self.deferred_pprinters:
388 if key in self.deferred_pprinters:
390 # Move the printer over to the regular registry.
389 # Move the printer over to the regular registry.
391 printer = self.deferred_pprinters.pop(key)
390 printer = self.deferred_pprinters.pop(key)
392 self.type_pprinters[cls] = printer
391 self.type_pprinters[cls] = printer
393 return printer
392 return printer
394
393
395
394
396 class Printable(object):
395 class Printable(object):
397
396
398 def output(self, stream, output_width):
397 def output(self, stream, output_width):
399 return output_width
398 return output_width
400
399
401
400
402 class Text(Printable):
401 class Text(Printable):
403
402
404 def __init__(self):
403 def __init__(self):
405 self.objs = []
404 self.objs = []
406 self.width = 0
405 self.width = 0
407
406
408 def output(self, stream, output_width):
407 def output(self, stream, output_width):
409 for obj in self.objs:
408 for obj in self.objs:
410 stream.write(obj)
409 stream.write(obj)
411 return output_width + self.width
410 return output_width + self.width
412
411
413 def add(self, obj, width):
412 def add(self, obj, width):
414 self.objs.append(obj)
413 self.objs.append(obj)
415 self.width += width
414 self.width += width
416
415
417
416
418 class Breakable(Printable):
417 class Breakable(Printable):
419
418
420 def __init__(self, seq, width, pretty):
419 def __init__(self, seq, width, pretty):
421 self.obj = seq
420 self.obj = seq
422 self.width = width
421 self.width = width
423 self.pretty = pretty
422 self.pretty = pretty
424 self.indentation = pretty.indentation
423 self.indentation = pretty.indentation
425 self.group = pretty.group_stack[-1]
424 self.group = pretty.group_stack[-1]
426 self.group.breakables.append(self)
425 self.group.breakables.append(self)
427
426
428 def output(self, stream, output_width):
427 def output(self, stream, output_width):
429 self.group.breakables.popleft()
428 self.group.breakables.popleft()
430 if self.group.want_break:
429 if self.group.want_break:
431 stream.write(self.pretty.newline)
430 stream.write(self.pretty.newline)
432 stream.write(' ' * self.indentation)
431 stream.write(' ' * self.indentation)
433 return self.indentation
432 return self.indentation
434 if not self.group.breakables:
433 if not self.group.breakables:
435 self.pretty.group_queue.remove(self.group)
434 self.pretty.group_queue.remove(self.group)
436 stream.write(self.obj)
435 stream.write(self.obj)
437 return output_width + self.width
436 return output_width + self.width
438
437
439
438
440 class Group(Printable):
439 class Group(Printable):
441
440
442 def __init__(self, depth):
441 def __init__(self, depth):
443 self.depth = depth
442 self.depth = depth
444 self.breakables = deque()
443 self.breakables = deque()
445 self.want_break = False
444 self.want_break = False
446
445
447
446
448 class GroupQueue(object):
447 class GroupQueue(object):
449
448
450 def __init__(self, *groups):
449 def __init__(self, *groups):
451 self.queue = []
450 self.queue = []
452 for group in groups:
451 for group in groups:
453 self.enq(group)
452 self.enq(group)
454
453
455 def enq(self, group):
454 def enq(self, group):
456 depth = group.depth
455 depth = group.depth
457 while depth > len(self.queue) - 1:
456 while depth > len(self.queue) - 1:
458 self.queue.append([])
457 self.queue.append([])
459 self.queue[depth].append(group)
458 self.queue[depth].append(group)
460
459
461 def deq(self):
460 def deq(self):
462 for stack in self.queue:
461 for stack in self.queue:
463 for idx, group in enumerate(reversed(stack)):
462 for idx, group in enumerate(reversed(stack)):
464 if group.breakables:
463 if group.breakables:
465 del stack[idx]
464 del stack[idx]
466 group.want_break = True
465 group.want_break = True
467 return group
466 return group
468 for group in stack:
467 for group in stack:
469 group.want_break = True
468 group.want_break = True
470 del stack[:]
469 del stack[:]
471
470
472 def remove(self, group):
471 def remove(self, group):
473 try:
472 try:
474 self.queue[group.depth].remove(group)
473 self.queue[group.depth].remove(group)
475 except ValueError:
474 except ValueError:
476 pass
475 pass
477
476
478 try:
477 try:
479 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
478 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
480 except AttributeError: # Python 3
479 except AttributeError: # Python 3
481 _baseclass_reprs = (object.__repr__,)
480 _baseclass_reprs = (object.__repr__,)
482
481
483
482
484 def _default_pprint(obj, p, cycle):
483 def _default_pprint(obj, p, cycle):
485 """
484 """
486 The default print function. Used if an object does not provide one and
485 The default print function. Used if an object does not provide one and
487 it's none of the builtin objects.
486 it's none of the builtin objects.
488 """
487 """
489 klass = getattr(obj, '__class__', None) or type(obj)
488 klass = getattr(obj, '__class__', None) or type(obj)
490 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
489 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
491 # A user-provided repr. Find newlines and replace them with p.break_()
490 # A user-provided repr. Find newlines and replace them with p.break_()
492 output = repr(obj)
491 output = repr(obj)
493 for idx,output_line in enumerate(output.splitlines()):
492 for idx,output_line in enumerate(output.splitlines()):
494 if idx:
493 if idx:
495 p.break_()
494 p.break_()
496 p.text(output_line)
495 p.text(output_line)
497 return
496 return
498 p.begin_group(1, '<')
497 p.begin_group(1, '<')
499 p.pretty(klass)
498 p.pretty(klass)
500 p.text(' at 0x%x' % id(obj))
499 p.text(' at 0x%x' % id(obj))
501 if cycle:
500 if cycle:
502 p.text(' ...')
501 p.text(' ...')
503 elif p.verbose:
502 elif p.verbose:
504 first = True
503 first = True
505 for key in dir(obj):
504 for key in dir(obj):
506 if not key.startswith('_'):
505 if not key.startswith('_'):
507 try:
506 try:
508 value = getattr(obj, key)
507 value = getattr(obj, key)
509 except AttributeError:
508 except AttributeError:
510 continue
509 continue
511 if isinstance(value, types.MethodType):
510 if isinstance(value, types.MethodType):
512 continue
511 continue
513 if not first:
512 if not first:
514 p.text(',')
513 p.text(',')
515 p.breakable()
514 p.breakable()
516 p.text(key)
515 p.text(key)
517 p.text('=')
516 p.text('=')
518 step = len(key) + 1
517 step = len(key) + 1
519 p.indentation += step
518 p.indentation += step
520 p.pretty(value)
519 p.pretty(value)
521 p.indentation -= step
520 p.indentation -= step
522 first = False
521 first = False
523 p.end_group(1, '>')
522 p.end_group(1, '>')
524
523
525
524
526 def _seq_pprinter_factory(start, end, basetype):
525 def _seq_pprinter_factory(start, end, basetype):
527 """
526 """
528 Factory that returns a pprint function useful for sequences. Used by
527 Factory that returns a pprint function useful for sequences. Used by
529 the default pprint for tuples, dicts, and lists.
528 the default pprint for tuples, dicts, and lists.
530 """
529 """
531 def inner(obj, p, cycle):
530 def inner(obj, p, cycle):
532 typ = type(obj)
531 typ = type(obj)
533 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
532 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
534 # If the subclass provides its own repr, use it instead.
533 # If the subclass provides its own repr, use it instead.
535 return p.text(typ.__repr__(obj))
534 return p.text(typ.__repr__(obj))
536
535
537 if cycle:
536 if cycle:
538 return p.text(start + '...' + end)
537 return p.text(start + '...' + end)
539 step = len(start)
538 step = len(start)
540 p.begin_group(step, start)
539 p.begin_group(step, start)
541 for idx, x in enumerate(obj):
540 for idx, x in enumerate(obj):
542 if idx:
541 if idx:
543 p.text(',')
542 p.text(',')
544 p.breakable()
543 p.breakable()
545 p.pretty(x)
544 p.pretty(x)
546 if len(obj) == 1 and type(obj) is tuple:
545 if len(obj) == 1 and type(obj) is tuple:
547 # Special case for 1-item tuples.
546 # Special case for 1-item tuples.
548 p.text(',')
547 p.text(',')
549 p.end_group(step, end)
548 p.end_group(step, end)
550 return inner
549 return inner
551
550
552
551
553 def _set_pprinter_factory(start, end, basetype):
552 def _set_pprinter_factory(start, end, basetype):
554 """
553 """
555 Factory that returns a pprint function useful for sets and frozensets.
554 Factory that returns a pprint function useful for sets and frozensets.
556 """
555 """
557 def inner(obj, p, cycle):
556 def inner(obj, p, cycle):
558 typ = type(obj)
557 typ = type(obj)
559 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
558 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
560 # If the subclass provides its own repr, use it instead.
559 # If the subclass provides its own repr, use it instead.
561 return p.text(typ.__repr__(obj))
560 return p.text(typ.__repr__(obj))
562
561
563 if cycle:
562 if cycle:
564 return p.text(start + '...' + end)
563 return p.text(start + '...' + end)
565 if len(obj) == 0:
564 if len(obj) == 0:
566 # Special case.
565 # Special case.
567 p.text(basetype.__name__ + '()')
566 p.text(basetype.__name__ + '()')
568 else:
567 else:
569 step = len(start)
568 step = len(start)
570 p.begin_group(step, start)
569 p.begin_group(step, start)
571 # Like dictionary keys, we will try to sort the items.
570 # Like dictionary keys, we will try to sort the items.
572 items = list(obj)
571 items = list(obj)
573 try:
572 try:
574 items.sort()
573 items.sort()
575 except Exception:
574 except Exception:
576 # Sometimes the items don't sort.
575 # Sometimes the items don't sort.
577 pass
576 pass
578 for idx, x in enumerate(items):
577 for idx, x in enumerate(items):
579 if idx:
578 if idx:
580 p.text(',')
579 p.text(',')
581 p.breakable()
580 p.breakable()
582 p.pretty(x)
581 p.pretty(x)
583 p.end_group(step, end)
582 p.end_group(step, end)
584 return inner
583 return inner
585
584
586
585
587 def _dict_pprinter_factory(start, end, basetype=None):
586 def _dict_pprinter_factory(start, end, basetype=None):
588 """
587 """
589 Factory that returns a pprint function used by the default pprint of
588 Factory that returns a pprint function used by the default pprint of
590 dicts and dict proxies.
589 dicts and dict proxies.
591 """
590 """
592 def inner(obj, p, cycle):
591 def inner(obj, p, cycle):
593 typ = type(obj)
592 typ = type(obj)
594 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
593 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
595 # If the subclass provides its own repr, use it instead.
594 # If the subclass provides its own repr, use it instead.
596 return p.text(typ.__repr__(obj))
595 return p.text(typ.__repr__(obj))
597
596
598 if cycle:
597 if cycle:
599 return p.text('{...}')
598 return p.text('{...}')
600 p.begin_group(1, start)
599 p.begin_group(1, start)
601 keys = obj.keys()
600 keys = obj.keys()
602 try:
601 try:
603 keys.sort()
602 keys.sort()
604 except Exception as e:
603 except Exception as e:
605 # Sometimes the keys don't sort.
604 # Sometimes the keys don't sort.
606 pass
605 pass
607 for idx, key in enumerate(keys):
606 for idx, key in enumerate(keys):
608 if idx:
607 if idx:
609 p.text(',')
608 p.text(',')
610 p.breakable()
609 p.breakable()
611 p.pretty(key)
610 p.pretty(key)
612 p.text(': ')
611 p.text(': ')
613 p.pretty(obj[key])
612 p.pretty(obj[key])
614 p.end_group(1, end)
613 p.end_group(1, end)
615 return inner
614 return inner
616
615
617
616
618 def _super_pprint(obj, p, cycle):
617 def _super_pprint(obj, p, cycle):
619 """The pprint for the super type."""
618 """The pprint for the super type."""
620 p.begin_group(8, '<super: ')
619 p.begin_group(8, '<super: ')
621 p.pretty(obj.__self_class__)
620 p.pretty(obj.__self_class__)
622 p.text(',')
621 p.text(',')
623 p.breakable()
622 p.breakable()
624 p.pretty(obj.__self__)
623 p.pretty(obj.__self__)
625 p.end_group(8, '>')
624 p.end_group(8, '>')
626
625
627
626
628 def _re_pattern_pprint(obj, p, cycle):
627 def _re_pattern_pprint(obj, p, cycle):
629 """The pprint function for regular expression patterns."""
628 """The pprint function for regular expression patterns."""
630 p.text('re.compile(')
629 p.text('re.compile(')
631 pattern = repr(obj.pattern)
630 pattern = repr(obj.pattern)
632 if pattern[:1] in 'uU':
631 if pattern[:1] in 'uU':
633 pattern = pattern[1:]
632 pattern = pattern[1:]
634 prefix = 'ur'
633 prefix = 'ur'
635 else:
634 else:
636 prefix = 'r'
635 prefix = 'r'
637 pattern = prefix + pattern.replace('\\\\', '\\')
636 pattern = prefix + pattern.replace('\\\\', '\\')
638 p.text(pattern)
637 p.text(pattern)
639 if obj.flags:
638 if obj.flags:
640 p.text(',')
639 p.text(',')
641 p.breakable()
640 p.breakable()
642 done_one = False
641 done_one = False
643 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
642 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
644 'UNICODE', 'VERBOSE', 'DEBUG'):
643 'UNICODE', 'VERBOSE', 'DEBUG'):
645 if obj.flags & getattr(re, flag):
644 if obj.flags & getattr(re, flag):
646 if done_one:
645 if done_one:
647 p.text('|')
646 p.text('|')
648 p.text('re.' + flag)
647 p.text('re.' + flag)
649 done_one = True
648 done_one = True
650 p.text(')')
649 p.text(')')
651
650
652
651
653 def _type_pprint(obj, p, cycle):
652 def _type_pprint(obj, p, cycle):
654 """The pprint for classes and types."""
653 """The pprint for classes and types."""
655 mod = getattr(obj, '__module__', None)
654 mod = getattr(obj, '__module__', None)
656 if mod is None:
655 if mod is None:
657 # Heap allocated types might not have the module attribute,
656 # Heap allocated types might not have the module attribute,
658 # and others may set it to None.
657 # and others may set it to None.
659 return p.text(obj.__name__)
658 return p.text(obj.__name__)
660
659
661 if mod in ('__builtin__', 'exceptions'):
660 if mod in ('__builtin__', 'builtins', 'exceptions'):
662 name = obj.__name__
661 name = obj.__name__
663 else:
662 else:
664 name = mod + '.' + obj.__name__
663 name = mod + '.' + obj.__name__
665 p.text(name)
664 p.text(name)
666
665
667
666
668 def _repr_pprint(obj, p, cycle):
667 def _repr_pprint(obj, p, cycle):
669 """A pprint that just redirects to the normal repr function."""
668 """A pprint that just redirects to the normal repr function."""
670 p.text(repr(obj))
669 p.text(repr(obj))
671
670
672
671
673 def _function_pprint(obj, p, cycle):
672 def _function_pprint(obj, p, cycle):
674 """Base pprint for all functions and builtin functions."""
673 """Base pprint for all functions and builtin functions."""
675 if obj.__module__ in ('__builtin__', 'exceptions') or not obj.__module__:
674 if obj.__module__ in ('__builtin__', 'builtins', 'exceptions') or not obj.__module__:
676 name = obj.__name__
675 name = obj.__name__
677 else:
676 else:
678 name = obj.__module__ + '.' + obj.__name__
677 name = obj.__module__ + '.' + obj.__name__
679 p.text('<function %s>' % name)
678 p.text('<function %s>' % name)
680
679
681
680
682 def _exception_pprint(obj, p, cycle):
681 def _exception_pprint(obj, p, cycle):
683 """Base pprint for all exceptions."""
682 """Base pprint for all exceptions."""
684 if obj.__class__.__module__ in ('exceptions', 'builtins'):
683 if obj.__class__.__module__ in ('exceptions', 'builtins'):
685 name = obj.__class__.__name__
684 name = obj.__class__.__name__
686 else:
685 else:
687 name = '%s.%s' % (
686 name = '%s.%s' % (
688 obj.__class__.__module__,
687 obj.__class__.__module__,
689 obj.__class__.__name__
688 obj.__class__.__name__
690 )
689 )
691 step = len(name) + 1
690 step = len(name) + 1
692 p.begin_group(step, name + '(')
691 p.begin_group(step, name + '(')
693 for idx, arg in enumerate(getattr(obj, 'args', ())):
692 for idx, arg in enumerate(getattr(obj, 'args', ())):
694 if idx:
693 if idx:
695 p.text(',')
694 p.text(',')
696 p.breakable()
695 p.breakable()
697 p.pretty(arg)
696 p.pretty(arg)
698 p.end_group(step, ')')
697 p.end_group(step, ')')
699
698
700
699
701 #: the exception base
700 #: the exception base
702 try:
701 try:
703 _exception_base = BaseException
702 _exception_base = BaseException
704 except NameError:
703 except NameError:
705 _exception_base = Exception
704 _exception_base = Exception
706
705
707
706
708 #: printers for builtin types
707 #: printers for builtin types
709 _type_pprinters = {
708 _type_pprinters = {
710 int: _repr_pprint,
709 int: _repr_pprint,
711 long: _repr_pprint,
710 long: _repr_pprint,
712 float: _repr_pprint,
711 float: _repr_pprint,
713 str: _repr_pprint,
712 str: _repr_pprint,
714 unicode: _repr_pprint,
713 unicode: _repr_pprint,
715 tuple: _seq_pprinter_factory('(', ')', tuple),
714 tuple: _seq_pprinter_factory('(', ')', tuple),
716 list: _seq_pprinter_factory('[', ']', list),
715 list: _seq_pprinter_factory('[', ']', list),
717 dict: _dict_pprinter_factory('{', '}', dict),
716 dict: _dict_pprinter_factory('{', '}', dict),
718
717
719 set: _set_pprinter_factory('{', '}', set),
718 set: _set_pprinter_factory('{', '}', set),
720 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
719 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
721 super: _super_pprint,
720 super: _super_pprint,
722 _re_pattern_type: _re_pattern_pprint,
721 _re_pattern_type: _re_pattern_pprint,
723 type: _type_pprint,
722 type: _type_pprint,
724 types.FunctionType: _function_pprint,
723 types.FunctionType: _function_pprint,
725 types.BuiltinFunctionType: _function_pprint,
724 types.BuiltinFunctionType: _function_pprint,
726 types.SliceType: _repr_pprint,
725 types.SliceType: _repr_pprint,
727 types.MethodType: _repr_pprint,
726 types.MethodType: _repr_pprint,
728
727
729 datetime.datetime: _repr_pprint,
728 datetime.datetime: _repr_pprint,
730 datetime.timedelta: _repr_pprint,
729 datetime.timedelta: _repr_pprint,
731 _exception_base: _exception_pprint
730 _exception_base: _exception_pprint
732 }
731 }
733
732
734 try:
733 try:
735 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
734 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
736 _type_pprinters[types.ClassType] = _type_pprint
735 _type_pprinters[types.ClassType] = _type_pprint
737 except AttributeError: # Python 3
736 except AttributeError: # Python 3
738 pass
737 pass
739
738
740 try:
739 try:
741 _type_pprinters[xrange] = _repr_pprint
740 _type_pprinters[xrange] = _repr_pprint
742 except NameError:
741 except NameError:
743 _type_pprinters[range] = _repr_pprint
742 _type_pprinters[range] = _repr_pprint
744
743
745 #: printers for types specified by name
744 #: printers for types specified by name
746 _deferred_type_pprinters = {
745 _deferred_type_pprinters = {
747 }
746 }
748
747
749 def for_type(typ, func):
748 def for_type(typ, func):
750 """
749 """
751 Add a pretty printer for a given type.
750 Add a pretty printer for a given type.
752 """
751 """
753 oldfunc = _type_pprinters.get(typ, None)
752 oldfunc = _type_pprinters.get(typ, None)
754 if func is not None:
753 if func is not None:
755 # To support easy restoration of old pprinters, we need to ignore Nones.
754 # To support easy restoration of old pprinters, we need to ignore Nones.
756 _type_pprinters[typ] = func
755 _type_pprinters[typ] = func
757 return oldfunc
756 return oldfunc
758
757
759 def for_type_by_name(type_module, type_name, func):
758 def for_type_by_name(type_module, type_name, func):
760 """
759 """
761 Add a pretty printer for a type specified by the module and name of a type
760 Add a pretty printer for a type specified by the module and name of a type
762 rather than the type object itself.
761 rather than the type object itself.
763 """
762 """
764 key = (type_module, type_name)
763 key = (type_module, type_name)
765 oldfunc = _deferred_type_pprinters.get(key, None)
764 oldfunc = _deferred_type_pprinters.get(key, None)
766 if func is not None:
765 if func is not None:
767 # To support easy restoration of old pprinters, we need to ignore Nones.
766 # To support easy restoration of old pprinters, we need to ignore Nones.
768 _deferred_type_pprinters[key] = func
767 _deferred_type_pprinters[key] = func
769 return oldfunc
768 return oldfunc
770
769
771
770
772 #: printers for the default singletons
771 #: printers for the default singletons
773 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
772 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
774 NotImplemented]), _repr_pprint)
773 NotImplemented]), _repr_pprint)
775
774
776
775
777 if __name__ == '__main__':
776 if __name__ == '__main__':
778 from random import randrange
777 from random import randrange
779 class Foo(object):
778 class Foo(object):
780 def __init__(self):
779 def __init__(self):
781 self.foo = 1
780 self.foo = 1
782 self.bar = re.compile(r'\s+')
781 self.bar = re.compile(r'\s+')
783 self.blub = dict.fromkeys(range(30), randrange(1, 40))
782 self.blub = dict.fromkeys(range(30), randrange(1, 40))
784 self.hehe = 23424.234234
783 self.hehe = 23424.234234
785 self.list = ["blub", "blah", self]
784 self.list = ["blub", "blah", self]
786
785
787 def get_foo(self):
786 def get_foo(self):
788 print "foo"
787 print "foo"
789
788
790 pprint(Foo(), verbose=True)
789 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now