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