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