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