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