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