##// END OF EJS Templates
BUG: Fix pretty-printing for overzealous objects that will return something non-callable for any requested attribute (thus confusing hasattr).
Robert Kern -
Show More
@@ -1,74 +1,91 b''
1 1 """Tests for the Formatters.
2 2 """
3 3
4 4 from math import pi
5 5
6 6 try:
7 7 import numpy
8 8 except:
9 9 numpy = None
10 10 import nose.tools as nt
11 11
12 12 from IPython.core.formatters import FormatterABC, PlainTextFormatter
13 from IPython.lib import pretty
13 14
14 15 class A(object):
15 16 def __repr__(self):
16 17 return 'A()'
17 18
18 19 class B(A):
19 20 def __repr__(self):
20 21 return 'B()'
21 22
23 class BadPretty(object):
24 _repr_pretty_ = None
25
26 class GoodPretty(object):
27 def _repr_pretty_(self, pp, cycle):
28 pp.text('foo')
29
30 def __repr__(self):
31 return 'GoodPretty()'
32
22 33 def foo_printer(obj, pp, cycle):
23 34 pp.text('foo')
24 35
25 36 def test_pretty():
26 37 f = PlainTextFormatter()
27 38 f.for_type(A, foo_printer)
28 39 nt.assert_equals(f(A()), 'foo')
29 40 nt.assert_equals(f(B()), 'foo')
41 nt.assert_equals(f(GoodPretty()), 'foo')
42 # Just don't raise an exception for the following:
43 f(BadPretty())
44
30 45 f.pprint = False
31 46 nt.assert_equals(f(A()), 'A()')
32 47 nt.assert_equals(f(B()), 'B()')
48 nt.assert_equals(f(GoodPretty()), 'GoodPretty()')
49
33 50
34 51 def test_deferred():
35 52 f = PlainTextFormatter()
36 53
37 54 def test_precision():
38 55 """test various values for float_precision."""
39 56 f = PlainTextFormatter()
40 57 nt.assert_equals(f(pi), repr(pi))
41 58 f.float_precision = 0
42 59 if numpy:
43 60 po = numpy.get_printoptions()
44 61 nt.assert_equals(po['precision'], 0)
45 62 nt.assert_equals(f(pi), '3')
46 63 f.float_precision = 2
47 64 if numpy:
48 65 po = numpy.get_printoptions()
49 66 nt.assert_equals(po['precision'], 2)
50 67 nt.assert_equals(f(pi), '3.14')
51 68 f.float_precision = '%g'
52 69 if numpy:
53 70 po = numpy.get_printoptions()
54 71 nt.assert_equals(po['precision'], 2)
55 72 nt.assert_equals(f(pi), '3.14159')
56 73 f.float_precision = '%e'
57 74 nt.assert_equals(f(pi), '3.141593e+00')
58 75 f.float_precision = ''
59 76 if numpy:
60 77 po = numpy.get_printoptions()
61 78 nt.assert_equals(po['precision'], 8)
62 79 nt.assert_equals(f(pi), repr(pi))
63 80
64 81 def test_bad_precision():
65 82 """test various invalid values for float_precision."""
66 83 f = PlainTextFormatter()
67 84 def set_fp(p):
68 85 f.float_precision=p
69 86 nt.assert_raises(ValueError, set_fp, '%')
70 87 nt.assert_raises(ValueError, set_fp, '%.3f%i')
71 88 nt.assert_raises(ValueError, set_fp, 'foo')
72 89 nt.assert_raises(ValueError, set_fp, -1)
73 90
74 91
@@ -1,725 +1,729 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 pretty
4 4 ~~
5 5
6 6 Python advanced pretty printer. This pretty printer is intended to
7 7 replace the old `pprint` python module which does not allow developers
8 8 to provide their own pretty print callbacks.
9 9
10 10 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
11 11
12 12
13 13 Example Usage
14 14 =============
15 15
16 16 To directly print the representation of an object use `pprint`::
17 17
18 18 from pretty import pprint
19 19 pprint(complex_object)
20 20
21 21 To get a string of the output use `pretty`::
22 22
23 23 from pretty import pretty
24 24 string = pretty(complex_object)
25 25
26 26
27 27 Extending
28 28 =========
29 29
30 30 The pretty library allows developers to add pretty printing rules for their
31 31 own objects. This process is straightforward. All you have to do is to
32 32 add a `_repr_pretty_` method to your object and call the methods on the
33 33 pretty printer passed::
34 34
35 35 class MyObject(object):
36 36
37 37 def _repr_pretty_(self, p, cycle):
38 38 ...
39 39
40 40 Depending on the python version you want to support you have two
41 41 possibilities. The following list shows the python 2.5 version and the
42 42 compatibility one.
43 43
44 44
45 45 Here the example implementation of a `_repr_pretty_` method for a list
46 46 subclass for python 2.5 and higher (python 2.5 requires the with statement
47 47 __future__ import)::
48 48
49 49 class MyList(list):
50 50
51 51 def _repr_pretty_(self, p, cycle):
52 52 if cycle:
53 53 p.text('MyList(...)')
54 54 else:
55 55 with p.group(8, 'MyList([', '])'):
56 56 for idx, item in enumerate(self):
57 57 if idx:
58 58 p.text(',')
59 59 p.breakable()
60 60 p.pretty(item)
61 61
62 62 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
63 63 react to that or the result is an infinite loop. `p.text()` just adds
64 64 non breaking text to the output, `p.breakable()` either adds a whitespace
65 65 or breaks here. If you pass it an argument it's used instead of the
66 66 default space. `p.pretty` prettyprints another object using the pretty print
67 67 method.
68 68
69 69 The first parameter to the `group` function specifies the extra indentation
70 70 of the next line. In this example the next item will either be not
71 71 breaked (if the items are short enough) or aligned with the right edge of
72 72 the opening bracked of `MyList`.
73 73
74 74 If you want to support python 2.4 and lower you can use this code::
75 75
76 76 class MyList(list):
77 77
78 78 def _repr_pretty_(self, p, cycle):
79 79 if cycle:
80 80 p.text('MyList(...)')
81 81 else:
82 82 p.begin_group(8, 'MyList([')
83 83 for idx, item in enumerate(self):
84 84 if idx:
85 85 p.text(',')
86 86 p.breakable()
87 87 p.pretty(item)
88 88 p.end_group(8, '])')
89 89
90 90 If you just want to indent something you can use the group function
91 91 without open / close parameters. Under python 2.5 you can also use this
92 92 code::
93 93
94 94 with p.indent(2):
95 95 ...
96 96
97 97 Or under python2.4 you might want to modify ``p.indentation`` by hand but
98 98 this is rather ugly.
99 99
100 100 :copyright: 2007 by Armin Ronacher.
101 101 Portions (c) 2009 by Robert Kern.
102 102 :license: BSD License.
103 103 """
104 104 from __future__ import with_statement
105 105 from contextlib import contextmanager
106 106 import sys
107 107 import types
108 108 import re
109 109 import datetime
110 110 from StringIO import StringIO
111 111 from collections import deque
112 112
113 113
114 114 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
115 115 'for_type', 'for_type_by_name']
116 116
117 117
118 118 _re_pattern_type = type(re.compile(''))
119 119
120 120
121 121 def pretty(obj, verbose=False, max_width=79, newline='\n'):
122 122 """
123 123 Pretty print the object's representation.
124 124 """
125 125 stream = StringIO()
126 126 printer = RepresentationPrinter(stream, verbose, max_width, newline)
127 127 printer.pretty(obj)
128 128 printer.flush()
129 129 return stream.getvalue()
130 130
131 131
132 132 def pprint(obj, verbose=False, max_width=79, newline='\n'):
133 133 """
134 134 Like `pretty` but print to stdout.
135 135 """
136 136 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
137 137 printer.pretty(obj)
138 138 printer.flush()
139 139 sys.stdout.write(newline)
140 140 sys.stdout.flush()
141 141
142 142 class _PrettyPrinterBase(object):
143 143
144 144 @contextmanager
145 145 def indent(self, indent):
146 146 """with statement support for indenting/dedenting."""
147 147 self.indentation += indent
148 148 try:
149 149 yield
150 150 finally:
151 151 self.indentation -= indent
152 152
153 153 @contextmanager
154 154 def group(self, indent=0, open='', close=''):
155 155 """like begin_group / end_group but for the with statement."""
156 156 self.begin_group(indent, open)
157 157 try:
158 158 with self.indent(indent):
159 159 yield
160 160 finally:
161 161 self.end_group(indent, close)
162 162
163 163 class PrettyPrinter(_PrettyPrinterBase):
164 164 """
165 165 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
166 166 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
167 167 this printer knows nothing about the default pprinters or the `_repr_pretty_`
168 168 callback method.
169 169 """
170 170
171 171 def __init__(self, output, max_width=79, newline='\n'):
172 172 self.output = output
173 173 self.max_width = max_width
174 174 self.newline = newline
175 175 self.output_width = 0
176 176 self.buffer_width = 0
177 177 self.buffer = deque()
178 178
179 179 root_group = Group(0)
180 180 self.group_stack = [root_group]
181 181 self.group_queue = GroupQueue(root_group)
182 182 self.indentation = 0
183 183
184 184 def _break_outer_groups(self):
185 185 while self.max_width < self.output_width + self.buffer_width:
186 186 group = self.group_queue.deq()
187 187 if not group:
188 188 return
189 189 while group.breakables:
190 190 x = self.buffer.popleft()
191 191 self.output_width = x.output(self.output, self.output_width)
192 192 self.buffer_width -= x.width
193 193 while self.buffer and isinstance(self.buffer[0], Text):
194 194 x = self.buffer.popleft()
195 195 self.output_width = x.output(self.output, self.output_width)
196 196 self.buffer_width -= x.width
197 197
198 198 def text(self, obj):
199 199 """Add literal text to the output."""
200 200 width = len(obj)
201 201 if self.buffer:
202 202 text = self.buffer[-1]
203 203 if not isinstance(text, Text):
204 204 text = Text()
205 205 self.buffer.append(text)
206 206 text.add(obj, width)
207 207 self.buffer_width += width
208 208 self._break_outer_groups()
209 209 else:
210 210 self.output.write(obj)
211 211 self.output_width += width
212 212
213 213 def breakable(self, sep=' '):
214 214 """
215 215 Add a breakable separator to the output. This does not mean that it
216 216 will automatically break here. If no breaking on this position takes
217 217 place the `sep` is inserted which default to one space.
218 218 """
219 219 width = len(sep)
220 220 group = self.group_stack[-1]
221 221 if group.want_break:
222 222 self.flush()
223 223 self.output.write(self.newline)
224 224 self.output.write(' ' * self.indentation)
225 225 self.output_width = self.indentation
226 226 self.buffer_width = 0
227 227 else:
228 228 self.buffer.append(Breakable(sep, width, self))
229 229 self.buffer_width += width
230 230 self._break_outer_groups()
231 231
232 232
233 233 def begin_group(self, indent=0, open=''):
234 234 """
235 235 Begin a group. If you want support for python < 2.5 which doesn't has
236 236 the with statement this is the preferred way:
237 237
238 238 p.begin_group(1, '{')
239 239 ...
240 240 p.end_group(1, '}')
241 241
242 242 The python 2.5 expression would be this:
243 243
244 244 with p.group(1, '{', '}'):
245 245 ...
246 246
247 247 The first parameter specifies the indentation for the next line (usually
248 248 the width of the opening text), the second the opening text. All
249 249 parameters are optional.
250 250 """
251 251 if open:
252 252 self.text(open)
253 253 group = Group(self.group_stack[-1].depth + 1)
254 254 self.group_stack.append(group)
255 255 self.group_queue.enq(group)
256 256 self.indentation += indent
257 257
258 258 def end_group(self, dedent=0, close=''):
259 259 """End a group. See `begin_group` for more details."""
260 260 self.indentation -= dedent
261 261 group = self.group_stack.pop()
262 262 if not group.breakables:
263 263 self.group_queue.remove(group)
264 264 if close:
265 265 self.text(close)
266 266
267 267 def flush(self):
268 268 """Flush data that is left in the buffer."""
269 269 for data in self.buffer:
270 270 self.output_width += data.output(self.output, self.output_width)
271 271 self.buffer.clear()
272 272 self.buffer_width = 0
273 273
274 274
275 275 def _get_mro(obj_class):
276 276 """ Get a reasonable method resolution order of a class and its superclasses
277 277 for both old-style and new-style classes.
278 278 """
279 279 if not hasattr(obj_class, '__mro__'):
280 280 # Old-style class. Mix in object to make a fake new-style class.
281 281 try:
282 282 obj_class = type(obj_class.__name__, (obj_class, object), {})
283 283 except TypeError:
284 284 # Old-style extension type that does not descend from object.
285 285 # FIXME: try to construct a more thorough MRO.
286 286 mro = [obj_class]
287 287 else:
288 288 mro = obj_class.__mro__[1:-1]
289 289 else:
290 290 mro = obj_class.__mro__
291 291 return mro
292 292
293 293
294 294 class RepresentationPrinter(PrettyPrinter):
295 295 """
296 296 Special pretty printer that has a `pretty` method that calls the pretty
297 297 printer for a python object.
298 298
299 299 This class stores processing data on `self` so you must *never* use
300 300 this class in a threaded environment. Always lock it or reinstanciate
301 301 it.
302 302
303 303 Instances also have a verbose flag callbacks can access to control their
304 304 output. For example the default instance repr prints all attributes and
305 305 methods that are not prefixed by an underscore if the printer is in
306 306 verbose mode.
307 307 """
308 308
309 309 def __init__(self, output, verbose=False, max_width=79, newline='\n',
310 310 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
311 311
312 312 PrettyPrinter.__init__(self, output, max_width, newline)
313 313 self.verbose = verbose
314 314 self.stack = []
315 315 if singleton_pprinters is None:
316 316 singleton_pprinters = _singleton_pprinters.copy()
317 317 self.singleton_pprinters = singleton_pprinters
318 318 if type_pprinters is None:
319 319 type_pprinters = _type_pprinters.copy()
320 320 self.type_pprinters = type_pprinters
321 321 if deferred_pprinters is None:
322 322 deferred_pprinters = _deferred_type_pprinters.copy()
323 323 self.deferred_pprinters = deferred_pprinters
324 324
325 325 def pretty(self, obj):
326 326 """Pretty print the given object."""
327 327 obj_id = id(obj)
328 328 cycle = obj_id in self.stack
329 329 self.stack.append(obj_id)
330 330 self.begin_group()
331 331 try:
332 332 obj_class = getattr(obj, '__class__', None) or type(obj)
333 333 # First try to find registered singleton printers for the type.
334 334 try:
335 335 printer = self.singleton_pprinters[obj_id]
336 336 except (TypeError, KeyError):
337 337 pass
338 338 else:
339 339 return printer(obj, self, cycle)
340 340 # Next look for type_printers.
341 341 for cls in _get_mro(obj_class):
342 342 if cls in self.type_pprinters:
343 343 return self.type_pprinters[cls](obj, self, cycle)
344 344 else:
345 345 printer = self._in_deferred_types(cls)
346 346 if printer is not None:
347 347 return printer(obj, self, cycle)
348 348 # Finally look for special method names.
349 349 if hasattr(obj_class, '_repr_pretty_'):
350 return obj_class._repr_pretty_(obj, self, cycle)
350 # Some objects automatically create any requested
351 # attribute. Try to ignore most of them by checking for
352 # callability.
353 if callable(obj_class._repr_pretty_):
354 return obj_class._repr_pretty_(obj, self, cycle)
351 355 return _default_pprint(obj, self, cycle)
352 356 finally:
353 357 self.end_group()
354 358 self.stack.pop()
355 359
356 360 def _in_deferred_types(self, cls):
357 361 """
358 362 Check if the given class is specified in the deferred type registry.
359 363
360 364 Returns the printer from the registry if it exists, and None if the
361 365 class is not in the registry. Successful matches will be moved to the
362 366 regular type registry for future use.
363 367 """
364 368 mod = getattr(cls, '__module__', None)
365 369 name = getattr(cls, '__name__', None)
366 370 key = (mod, name)
367 371 printer = None
368 372 if key in self.deferred_pprinters:
369 373 # Move the printer over to the regular registry.
370 374 printer = self.deferred_pprinters.pop(key)
371 375 self.type_pprinters[cls] = printer
372 376 return printer
373 377
374 378
375 379 class Printable(object):
376 380
377 381 def output(self, stream, output_width):
378 382 return output_width
379 383
380 384
381 385 class Text(Printable):
382 386
383 387 def __init__(self):
384 388 self.objs = []
385 389 self.width = 0
386 390
387 391 def output(self, stream, output_width):
388 392 for obj in self.objs:
389 393 stream.write(obj)
390 394 return output_width + self.width
391 395
392 396 def add(self, obj, width):
393 397 self.objs.append(obj)
394 398 self.width += width
395 399
396 400
397 401 class Breakable(Printable):
398 402
399 403 def __init__(self, seq, width, pretty):
400 404 self.obj = seq
401 405 self.width = width
402 406 self.pretty = pretty
403 407 self.indentation = pretty.indentation
404 408 self.group = pretty.group_stack[-1]
405 409 self.group.breakables.append(self)
406 410
407 411 def output(self, stream, output_width):
408 412 self.group.breakables.popleft()
409 413 if self.group.want_break:
410 414 stream.write(self.pretty.newline)
411 415 stream.write(' ' * self.indentation)
412 416 return self.indentation
413 417 if not self.group.breakables:
414 418 self.pretty.group_queue.remove(self.group)
415 419 stream.write(self.obj)
416 420 return output_width + self.width
417 421
418 422
419 423 class Group(Printable):
420 424
421 425 def __init__(self, depth):
422 426 self.depth = depth
423 427 self.breakables = deque()
424 428 self.want_break = False
425 429
426 430
427 431 class GroupQueue(object):
428 432
429 433 def __init__(self, *groups):
430 434 self.queue = []
431 435 for group in groups:
432 436 self.enq(group)
433 437
434 438 def enq(self, group):
435 439 depth = group.depth
436 440 while depth > len(self.queue) - 1:
437 441 self.queue.append([])
438 442 self.queue[depth].append(group)
439 443
440 444 def deq(self):
441 445 for stack in self.queue:
442 446 for idx, group in enumerate(reversed(stack)):
443 447 if group.breakables:
444 448 del stack[idx]
445 449 group.want_break = True
446 450 return group
447 451 for group in stack:
448 452 group.want_break = True
449 453 del stack[:]
450 454
451 455 def remove(self, group):
452 456 try:
453 457 self.queue[group.depth].remove(group)
454 458 except ValueError:
455 459 pass
456 460
457 461 try:
458 462 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
459 463 except AttributeError: # Python 3
460 464 _baseclass_reprs = (object.__repr__,)
461 465
462 466
463 467 def _default_pprint(obj, p, cycle):
464 468 """
465 469 The default print function. Used if an object does not provide one and
466 470 it's none of the builtin objects.
467 471 """
468 472 klass = getattr(obj, '__class__', None) or type(obj)
469 473 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
470 474 # A user-provided repr.
471 475 p.text(repr(obj))
472 476 return
473 477 p.begin_group(1, '<')
474 478 p.pretty(klass)
475 479 p.text(' at 0x%x' % id(obj))
476 480 if cycle:
477 481 p.text(' ...')
478 482 elif p.verbose:
479 483 first = True
480 484 for key in dir(obj):
481 485 if not key.startswith('_'):
482 486 try:
483 487 value = getattr(obj, key)
484 488 except AttributeError:
485 489 continue
486 490 if isinstance(value, types.MethodType):
487 491 continue
488 492 if not first:
489 493 p.text(',')
490 494 p.breakable()
491 495 p.text(key)
492 496 p.text('=')
493 497 step = len(key) + 1
494 498 p.indentation += step
495 499 p.pretty(value)
496 500 p.indentation -= step
497 501 first = False
498 502 p.end_group(1, '>')
499 503
500 504
501 505 def _seq_pprinter_factory(start, end, basetype):
502 506 """
503 507 Factory that returns a pprint function useful for sequences. Used by
504 508 the default pprint for tuples, dicts, lists, sets and frozensets.
505 509 """
506 510 def inner(obj, p, cycle):
507 511 typ = type(obj)
508 512 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
509 513 # If the subclass provides its own repr, use it instead.
510 514 return p.text(typ.__repr__(obj))
511 515
512 516 if cycle:
513 517 return p.text(start + '...' + end)
514 518 step = len(start)
515 519 p.begin_group(step, start)
516 520 for idx, x in enumerate(obj):
517 521 if idx:
518 522 p.text(',')
519 523 p.breakable()
520 524 p.pretty(x)
521 525 if len(obj) == 1 and type(obj) is tuple:
522 526 # Special case for 1-item tuples.
523 527 p.text(',')
524 528 p.end_group(step, end)
525 529 return inner
526 530
527 531
528 532 def _dict_pprinter_factory(start, end, basetype=None):
529 533 """
530 534 Factory that returns a pprint function used by the default pprint of
531 535 dicts and dict proxies.
532 536 """
533 537 def inner(obj, p, cycle):
534 538 typ = type(obj)
535 539 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
536 540 # If the subclass provides its own repr, use it instead.
537 541 return p.text(typ.__repr__(obj))
538 542
539 543 if cycle:
540 544 return p.text('{...}')
541 545 p.begin_group(1, start)
542 546 keys = obj.keys()
543 547 try:
544 548 keys.sort()
545 549 except Exception, e:
546 550 # Sometimes the keys don't sort.
547 551 pass
548 552 for idx, key in enumerate(keys):
549 553 if idx:
550 554 p.text(',')
551 555 p.breakable()
552 556 p.pretty(key)
553 557 p.text(': ')
554 558 p.pretty(obj[key])
555 559 p.end_group(1, end)
556 560 return inner
557 561
558 562
559 563 def _super_pprint(obj, p, cycle):
560 564 """The pprint for the super type."""
561 565 p.begin_group(8, '<super: ')
562 566 p.pretty(obj.__self_class__)
563 567 p.text(',')
564 568 p.breakable()
565 569 p.pretty(obj.__self__)
566 570 p.end_group(8, '>')
567 571
568 572
569 573 def _re_pattern_pprint(obj, p, cycle):
570 574 """The pprint function for regular expression patterns."""
571 575 p.text('re.compile(')
572 576 pattern = repr(obj.pattern)
573 577 if pattern[:1] in 'uU':
574 578 pattern = pattern[1:]
575 579 prefix = 'ur'
576 580 else:
577 581 prefix = 'r'
578 582 pattern = prefix + pattern.replace('\\\\', '\\')
579 583 p.text(pattern)
580 584 if obj.flags:
581 585 p.text(',')
582 586 p.breakable()
583 587 done_one = False
584 588 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
585 589 'UNICODE', 'VERBOSE', 'DEBUG'):
586 590 if obj.flags & getattr(re, flag):
587 591 if done_one:
588 592 p.text('|')
589 593 p.text('re.' + flag)
590 594 done_one = True
591 595 p.text(')')
592 596
593 597
594 598 def _type_pprint(obj, p, cycle):
595 599 """The pprint for classes and types."""
596 600 if obj.__module__ in ('__builtin__', 'exceptions'):
597 601 name = obj.__name__
598 602 else:
599 603 name = obj.__module__ + '.' + obj.__name__
600 604 p.text(name)
601 605
602 606
603 607 def _repr_pprint(obj, p, cycle):
604 608 """A pprint that just redirects to the normal repr function."""
605 609 p.text(repr(obj))
606 610
607 611
608 612 def _function_pprint(obj, p, cycle):
609 613 """Base pprint for all functions and builtin functions."""
610 614 if obj.__module__ in ('__builtin__', 'exceptions') or not obj.__module__:
611 615 name = obj.__name__
612 616 else:
613 617 name = obj.__module__ + '.' + obj.__name__
614 618 p.text('<function %s>' % name)
615 619
616 620
617 621 def _exception_pprint(obj, p, cycle):
618 622 """Base pprint for all exceptions."""
619 623 if obj.__class__.__module__ == 'exceptions':
620 624 name = obj.__class__.__name__
621 625 else:
622 626 name = '%s.%s' % (
623 627 obj.__class__.__module__,
624 628 obj.__class__.__name__
625 629 )
626 630 step = len(name) + 1
627 631 p.begin_group(step, '(')
628 632 for idx, arg in enumerate(getattr(obj, 'args', ())):
629 633 if idx:
630 634 p.text(',')
631 635 p.breakable()
632 636 p.pretty(arg)
633 637 p.end_group(step, ')')
634 638
635 639
636 640 #: the exception base
637 641 try:
638 642 _exception_base = BaseException
639 643 except NameError:
640 644 _exception_base = Exception
641 645
642 646
643 647 #: printers for builtin types
644 648 _type_pprinters = {
645 649 int: _repr_pprint,
646 650 long: _repr_pprint,
647 651 float: _repr_pprint,
648 652 str: _repr_pprint,
649 653 unicode: _repr_pprint,
650 654 tuple: _seq_pprinter_factory('(', ')', tuple),
651 655 list: _seq_pprinter_factory('[', ']', list),
652 656 dict: _dict_pprinter_factory('{', '}', dict),
653 657
654 658 set: _seq_pprinter_factory('set([', '])', set),
655 659 frozenset: _seq_pprinter_factory('frozenset([', '])', frozenset),
656 660 super: _super_pprint,
657 661 _re_pattern_type: _re_pattern_pprint,
658 662 type: _type_pprint,
659 663 types.FunctionType: _function_pprint,
660 664 types.BuiltinFunctionType: _function_pprint,
661 665 types.SliceType: _repr_pprint,
662 666 types.MethodType: _repr_pprint,
663 667
664 668 datetime.datetime: _repr_pprint,
665 669 datetime.timedelta: _repr_pprint,
666 670 _exception_base: _exception_pprint
667 671 }
668 672
669 673 try:
670 674 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
671 675 _type_pprinters[types.ClassType] = _type_pprint
672 676 except AttributeError: # Python 3
673 677 pass
674 678
675 679 try:
676 680 _type_pprinters[xrange] = _repr_pprint
677 681 except NameError:
678 682 _type_pprinters[range] = _repr_pprint
679 683
680 684 #: printers for types specified by name
681 685 _deferred_type_pprinters = {
682 686 }
683 687
684 688 def for_type(typ, func):
685 689 """
686 690 Add a pretty printer for a given type.
687 691 """
688 692 oldfunc = _type_pprinters.get(typ, None)
689 693 if func is not None:
690 694 # To support easy restoration of old pprinters, we need to ignore Nones.
691 695 _type_pprinters[typ] = func
692 696 return oldfunc
693 697
694 698 def for_type_by_name(type_module, type_name, func):
695 699 """
696 700 Add a pretty printer for a type specified by the module and name of a type
697 701 rather than the type object itself.
698 702 """
699 703 key = (type_module, type_name)
700 704 oldfunc = _deferred_type_pprinters.get(key, None)
701 705 if func is not None:
702 706 # To support easy restoration of old pprinters, we need to ignore Nones.
703 707 _deferred_type_pprinters[key] = func
704 708 return oldfunc
705 709
706 710
707 711 #: printers for the default singletons
708 712 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
709 713 NotImplemented]), _repr_pprint)
710 714
711 715
712 716 if __name__ == '__main__':
713 717 from random import randrange
714 718 class Foo(object):
715 719 def __init__(self):
716 720 self.foo = 1
717 721 self.bar = re.compile(r'\s+')
718 722 self.blub = dict.fromkeys(range(30), randrange(1, 40))
719 723 self.hehe = 23424.234234
720 724 self.list = ["blub", "blah", self]
721 725
722 726 def get_foo(self):
723 727 print "foo"
724 728
725 729 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now