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