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