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