##// END OF EJS Templates
BUG: Partial fix for the case of old-style extension types that do not descend from object, like the VTK types. Still need to work on getting a real MRO for them.
Robert Kern -
Show More
@@ -1,699 +1,705 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 `__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 __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 `__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 __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 __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 import __future__
105 105 import sys
106 106 import types
107 107 import re
108 108 import datetime
109 109 from StringIO import StringIO
110 110 from collections import deque
111 111
112 112
113 113 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
114 114 'for_type', 'for_type_by_name']
115 115
116 116
117 117 _re_pattern_type = type(re.compile(''))
118 118
119 119
120 120 def pretty(obj, verbose=False, max_width=79, newline='\n'):
121 121 """
122 122 Pretty print the object's representation.
123 123 """
124 124 stream = StringIO()
125 125 printer = RepresentationPrinter(stream, verbose, max_width, newline)
126 126 printer.pretty(obj)
127 127 printer.flush()
128 128 return stream.getvalue()
129 129
130 130
131 131 def pprint(obj, verbose=False, max_width=79, newline='\n'):
132 132 """
133 133 Like `pretty` but print to stdout.
134 134 """
135 135 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
136 136 printer.pretty(obj)
137 137 printer.flush()
138 138 sys.stdout.write(newline)
139 139 sys.stdout.flush()
140 140
141 141
142 142 # add python2.5 context managers if we have the with statement feature
143 143 if hasattr(__future__, 'with_statement'): exec '''
144 144 from __future__ import with_statement
145 145 from contextlib import contextmanager
146 146
147 147 class _PrettyPrinterBase(object):
148 148
149 149 @contextmanager
150 150 def indent(self, indent):
151 151 """with statement support for indenting/dedenting."""
152 152 self.indentation += indent
153 153 try:
154 154 yield
155 155 finally:
156 156 self.indentation -= indent
157 157
158 158 @contextmanager
159 159 def group(self, indent=0, open='', close=''):
160 160 """like begin_group / end_group but for the with statement."""
161 161 self.begin_group(indent, open)
162 162 try:
163 163 with self.indent(indent):
164 164 yield
165 165 finally:
166 166 self.end_group(indent, close)
167 167 '''
168 168 else:
169 169 class _PrettyPrinterBase(object):
170 170
171 171 def _unsupported(self, *a, **kw):
172 172 """unsupported operation"""
173 173 raise RuntimeError('not available in this python version')
174 174 group = indent = _unsupported
175 175 del _unsupported
176 176
177 177
178 178 class PrettyPrinter(_PrettyPrinterBase):
179 179 """
180 180 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
181 181 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
182 182 this printer knows nothing about the default pprinters or the `__pretty__`
183 183 callback method.
184 184 """
185 185
186 186 def __init__(self, output, max_width=79, newline='\n'):
187 187 self.output = output
188 188 self.max_width = max_width
189 189 self.newline = newline
190 190 self.output_width = 0
191 191 self.buffer_width = 0
192 192 self.buffer = deque()
193 193
194 194 root_group = Group(0)
195 195 self.group_stack = [root_group]
196 196 self.group_queue = GroupQueue(root_group)
197 197 self.indentation = 0
198 198
199 199 def _break_outer_groups(self):
200 200 while self.max_width < self.output_width + self.buffer_width:
201 201 group = self.group_queue.deq()
202 202 if not group:
203 203 return
204 204 while group.breakables:
205 205 x = self.buffer.popleft()
206 206 self.output_width = x.output(self.output, self.output_width)
207 207 self.buffer_width -= x.width
208 208 while self.buffer and isinstance(self.buffer[0], Text):
209 209 x = self.buffer.popleft()
210 210 self.output_width = x.output(self.output, self.output_width)
211 211 self.buffer_width -= x.width
212 212
213 213 def text(self, obj):
214 214 """Add literal text to the output."""
215 215 width = len(obj)
216 216 if self.buffer:
217 217 text = self.buffer[-1]
218 218 if not isinstance(text, Text):
219 219 text = Text()
220 220 self.buffer.append(text)
221 221 text.add(obj, width)
222 222 self.buffer_width += width
223 223 self._break_outer_groups()
224 224 else:
225 225 self.output.write(obj)
226 226 self.output_width += width
227 227
228 228 def breakable(self, sep=' '):
229 229 """
230 230 Add a breakable separator to the output. This does not mean that it
231 231 will automatically break here. If no breaking on this position takes
232 232 place the `sep` is inserted which default to one space.
233 233 """
234 234 width = len(sep)
235 235 group = self.group_stack[-1]
236 236 if group.want_break:
237 237 self.flush()
238 238 self.output.write(self.newline)
239 239 self.output.write(' ' * self.indentation)
240 240 self.output_width = self.indentation
241 241 self.buffer_width = 0
242 242 else:
243 243 self.buffer.append(Breakable(sep, width, self))
244 244 self.buffer_width += width
245 245 self._break_outer_groups()
246 246
247 247
248 248 def begin_group(self, indent=0, open=''):
249 249 """
250 250 Begin a group. If you want support for python < 2.5 which doesn't has
251 251 the with statement this is the preferred way:
252 252
253 253 p.begin_group(1, '{')
254 254 ...
255 255 p.end_group(1, '}')
256 256
257 257 The python 2.5 expression would be this:
258 258
259 259 with p.group(1, '{', '}'):
260 260 ...
261 261
262 262 The first parameter specifies the indentation for the next line (usually
263 263 the width of the opening text), the second the opening text. All
264 264 parameters are optional.
265 265 """
266 266 if open:
267 267 self.text(open)
268 268 group = Group(self.group_stack[-1].depth + 1)
269 269 self.group_stack.append(group)
270 270 self.group_queue.enq(group)
271 271 self.indentation += indent
272 272
273 273 def end_group(self, dedent=0, close=''):
274 274 """End a group. See `begin_group` for more details."""
275 275 self.indentation -= dedent
276 276 group = self.group_stack.pop()
277 277 if not group.breakables:
278 278 self.group_queue.remove(group)
279 279 if close:
280 280 self.text(close)
281 281
282 282 def flush(self):
283 283 """Flush data that is left in the buffer."""
284 284 for data in self.buffer:
285 285 self.output_width += data.output(self.output, self.output_width)
286 286 self.buffer.clear()
287 287 self.buffer_width = 0
288 288
289 289
290 290 def _get_mro(obj_class):
291 291 """ Get a reasonable method resolution order of a class and its superclasses
292 292 for both old-style and new-style classes.
293 293 """
294 294 if not hasattr(obj_class, '__mro__'):
295 295 # Old-style class. Mix in object to make a fake new-style class.
296 try:
296 297 obj_class = type(obj_class.__name__, (obj_class, object), {})
298 except TypeError:
299 # Old-style extension type that does not descend from object.
300 # FIXME: try to construct a more thorough MRO.
301 mro = [obj_class]
302 else:
297 303 mro = obj_class.__mro__[1:-1]
298 304 else:
299 305 mro = obj_class.__mro__
300 306 return mro
301 307
302 308
303 309 class RepresentationPrinter(PrettyPrinter):
304 310 """
305 311 Special pretty printer that has a `pretty` method that calls the pretty
306 312 printer for a python object.
307 313
308 314 This class stores processing data on `self` so you must *never* use
309 315 this class in a threaded environment. Always lock it or reinstanciate
310 316 it.
311 317
312 318 Instances also have a verbose flag callbacks can access to control their
313 319 output. For example the default instance repr prints all attributes and
314 320 methods that are not prefixed by an underscore if the printer is in
315 321 verbose mode.
316 322 """
317 323
318 324 def __init__(self, output, verbose=False, max_width=79, newline='\n'):
319 325 PrettyPrinter.__init__(self, output, max_width, newline)
320 326 self.verbose = verbose
321 327 self.stack = []
322 328
323 329 def pretty(self, obj):
324 330 """Pretty print the given object."""
325 331 obj_id = id(obj)
326 332 cycle = obj_id in self.stack
327 333 self.stack.append(obj_id)
328 334 self.begin_group()
329 335 try:
330 336 obj_class = getattr(obj, '__class__', None) or type(obj)
331 337 if hasattr(obj_class, '__pretty__'):
332 338 return obj_class.__pretty__(obj, self, cycle)
333 339 try:
334 340 printer = _singleton_pprinters[obj_id]
335 341 except (TypeError, KeyError):
336 342 pass
337 343 else:
338 344 return printer(obj, self, cycle)
339 345 for cls in _get_mro(obj_class):
340 346 if cls in _type_pprinters:
341 347 return _type_pprinters[cls](obj, self, cycle)
342 348 else:
343 349 printer = self._in_deferred_types(cls)
344 350 if printer is not None:
345 351 return printer(obj, self, cycle)
346 352 return _default_pprint(obj, self, cycle)
347 353 finally:
348 354 self.end_group()
349 355 self.stack.pop()
350 356
351 357 def _in_deferred_types(self, cls):
352 358 """
353 359 Check if the given class is specified in the deferred type registry.
354 360
355 361 Returns the printer from the registry if it exists, and None if the
356 362 class is not in the registry. Successful matches will be moved to the
357 363 regular type registry for future use.
358 364 """
359 365 mod = getattr(cls, '__module__', None)
360 366 name = getattr(cls, '__name__', None)
361 367 key = (mod, name)
362 368 printer = None
363 369 if key in _deferred_type_pprinters:
364 370 # Move the printer over to the regular registry.
365 371 printer = _deferred_type_pprinters.pop(key)
366 372 _type_pprinters[cls] = printer
367 373 return printer
368 374
369 375
370 376
371 377 class Printable(object):
372 378
373 379 def output(self, stream, output_width):
374 380 return output_width
375 381
376 382
377 383 class Text(Printable):
378 384
379 385 def __init__(self):
380 386 self.objs = []
381 387 self.width = 0
382 388
383 389 def output(self, stream, output_width):
384 390 for obj in self.objs:
385 391 stream.write(obj)
386 392 return output_width + self.width
387 393
388 394 def add(self, obj, width):
389 395 self.objs.append(obj)
390 396 self.width += width
391 397
392 398
393 399 class Breakable(Printable):
394 400
395 401 def __init__(self, seq, width, pretty):
396 402 self.obj = seq
397 403 self.width = width
398 404 self.pretty = pretty
399 405 self.indentation = pretty.indentation
400 406 self.group = pretty.group_stack[-1]
401 407 self.group.breakables.append(self)
402 408
403 409 def output(self, stream, output_width):
404 410 self.group.breakables.popleft()
405 411 if self.group.want_break:
406 412 stream.write(self.pretty.newline)
407 413 stream.write(' ' * self.indentation)
408 414 return self.indentation
409 415 if not self.group.breakables:
410 416 self.pretty.group_queue.remove(self.group)
411 417 stream.write(self.obj)
412 418 return output_width + self.width
413 419
414 420
415 421 class Group(Printable):
416 422
417 423 def __init__(self, depth):
418 424 self.depth = depth
419 425 self.breakables = deque()
420 426 self.want_break = False
421 427
422 428
423 429 class GroupQueue(object):
424 430
425 431 def __init__(self, *groups):
426 432 self.queue = []
427 433 for group in groups:
428 434 self.enq(group)
429 435
430 436 def enq(self, group):
431 437 depth = group.depth
432 438 while depth > len(self.queue) - 1:
433 439 self.queue.append([])
434 440 self.queue[depth].append(group)
435 441
436 442 def deq(self):
437 443 for stack in self.queue:
438 444 for idx, group in enumerate(reversed(stack)):
439 445 if group.breakables:
440 446 del stack[idx]
441 447 group.want_break = True
442 448 return group
443 449 for group in stack:
444 450 group.want_break = True
445 451 del stack[:]
446 452
447 453 def remove(self, group):
448 454 try:
449 455 self.queue[group.depth].remove(group)
450 456 except ValueError:
451 457 pass
452 458
453 459
454 460 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
455 461
456 462
457 463 def _default_pprint(obj, p, cycle):
458 464 """
459 465 The default print function. Used if an object does not provide one and
460 466 it's none of the builtin objects.
461 467 """
462 468 klass = getattr(obj, '__class__', None) or type(obj)
463 469 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
464 470 # A user-provided repr.
465 471 p.text(repr(obj))
466 472 return
467 473 p.begin_group(1, '<')
468 474 p.pretty(klass)
469 475 p.text(' at 0x%x' % id(obj))
470 476 if cycle:
471 477 p.text(' ...')
472 478 elif p.verbose:
473 479 first = True
474 480 for key in dir(obj):
475 481 if not key.startswith('_'):
476 482 try:
477 483 value = getattr(obj, key)
478 484 except AttributeError:
479 485 continue
480 486 if isinstance(value, types.MethodType):
481 487 continue
482 488 if not first:
483 489 p.text(',')
484 490 p.breakable()
485 491 p.text(key)
486 492 p.text('=')
487 493 step = len(key) + 1
488 494 p.indentation += step
489 495 p.pretty(value)
490 496 p.indentation -= step
491 497 first = False
492 498 p.end_group(1, '>')
493 499
494 500
495 501 def _seq_pprinter_factory(start, end):
496 502 """
497 503 Factory that returns a pprint function useful for sequences. Used by
498 504 the default pprint for tuples, dicts, lists, sets and frozensets.
499 505 """
500 506 def inner(obj, p, cycle):
501 507 if cycle:
502 508 return p.text(start + '...' + end)
503 509 step = len(start)
504 510 p.begin_group(step, start)
505 511 for idx, x in enumerate(obj):
506 512 if idx:
507 513 p.text(',')
508 514 p.breakable()
509 515 p.pretty(x)
510 516 if len(obj) == 1 and type(obj) is tuple:
511 517 # Special case for 1-item tuples.
512 518 p.text(',')
513 519 p.end_group(step, end)
514 520 return inner
515 521
516 522
517 523 def _dict_pprinter_factory(start, end):
518 524 """
519 525 Factory that returns a pprint function used by the default pprint of
520 526 dicts and dict proxies.
521 527 """
522 528 def inner(obj, p, cycle):
523 529 if cycle:
524 530 return p.text('{...}')
525 531 p.begin_group(1, start)
526 532 keys = obj.keys()
527 533 try:
528 534 keys.sort()
529 535 except Exception, e:
530 536 # Sometimes the keys don't sort.
531 537 pass
532 538 for idx, key in enumerate(keys):
533 539 if idx:
534 540 p.text(',')
535 541 p.breakable()
536 542 p.pretty(key)
537 543 p.text(': ')
538 544 p.pretty(obj[key])
539 545 p.end_group(1, end)
540 546 return inner
541 547
542 548
543 549 def _super_pprint(obj, p, cycle):
544 550 """The pprint for the super type."""
545 551 p.begin_group(8, '<super: ')
546 552 p.pretty(obj.__self_class__)
547 553 p.text(',')
548 554 p.breakable()
549 555 p.pretty(obj.__self__)
550 556 p.end_group(8, '>')
551 557
552 558
553 559 def _re_pattern_pprint(obj, p, cycle):
554 560 """The pprint function for regular expression patterns."""
555 561 p.text('re.compile(')
556 562 pattern = repr(obj.pattern)
557 563 if pattern[:1] in 'uU':
558 564 pattern = pattern[1:]
559 565 prefix = 'ur'
560 566 else:
561 567 prefix = 'r'
562 568 pattern = prefix + pattern.replace('\\\\', '\\')
563 569 p.text(pattern)
564 570 if obj.flags:
565 571 p.text(',')
566 572 p.breakable()
567 573 done_one = False
568 574 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
569 575 'UNICODE', 'VERBOSE', 'DEBUG'):
570 576 if obj.flags & getattr(re, flag):
571 577 if done_one:
572 578 p.text('|')
573 579 p.text('re.' + flag)
574 580 done_one = True
575 581 p.text(')')
576 582
577 583
578 584 def _type_pprint(obj, p, cycle):
579 585 """The pprint for classes and types."""
580 586 if obj.__module__ in ('__builtin__', 'exceptions'):
581 587 name = obj.__name__
582 588 else:
583 589 name = obj.__module__ + '.' + obj.__name__
584 590 p.text(name)
585 591
586 592
587 593 def _repr_pprint(obj, p, cycle):
588 594 """A pprint that just redirects to the normal repr function."""
589 595 p.text(repr(obj))
590 596
591 597
592 598 def _function_pprint(obj, p, cycle):
593 599 """Base pprint for all functions and builtin functions."""
594 600 if obj.__module__ in ('__builtin__', 'exceptions') or not obj.__module__:
595 601 name = obj.__name__
596 602 else:
597 603 name = obj.__module__ + '.' + obj.__name__
598 604 p.text('<function %s>' % name)
599 605
600 606
601 607 def _exception_pprint(obj, p, cycle):
602 608 """Base pprint for all exceptions."""
603 609 if obj.__class__.__module__ == 'exceptions':
604 610 name = obj.__class__.__name__
605 611 else:
606 612 name = '%s.%s' % (
607 613 obj.__class__.__module__,
608 614 obj.__class__.__name__
609 615 )
610 616 step = len(name) + 1
611 617 p.begin_group(step, '(')
612 618 for idx, arg in enumerate(getattr(obj, 'args', ())):
613 619 if idx:
614 620 p.text(',')
615 621 p.breakable()
616 622 p.pretty(arg)
617 623 p.end_group(step, ')')
618 624
619 625
620 626 #: the exception base
621 627 try:
622 628 _exception_base = BaseException
623 629 except NameError:
624 630 _exception_base = Exception
625 631
626 632
627 633 #: printers for builtin types
628 634 _type_pprinters = {
629 635 int: _repr_pprint,
630 636 long: _repr_pprint,
631 637 float: _repr_pprint,
632 638 str: _repr_pprint,
633 639 unicode: _repr_pprint,
634 640 tuple: _seq_pprinter_factory('(', ')'),
635 641 list: _seq_pprinter_factory('[', ']'),
636 642 dict: _dict_pprinter_factory('{', '}'),
637 643 types.DictProxyType: _dict_pprinter_factory('<dictproxy {', '}>'),
638 644 set: _seq_pprinter_factory('set([', '])'),
639 645 frozenset: _seq_pprinter_factory('frozenset([', '])'),
640 646 super: _super_pprint,
641 647 _re_pattern_type: _re_pattern_pprint,
642 648 type: _type_pprint,
643 649 types.ClassType: _type_pprint,
644 650 types.FunctionType: _function_pprint,
645 651 types.BuiltinFunctionType: _function_pprint,
646 652 types.SliceType: _repr_pprint,
647 653 types.MethodType: _repr_pprint,
648 654 xrange: _repr_pprint,
649 655 datetime.datetime: _repr_pprint,
650 656 datetime.timedelta: _repr_pprint,
651 657 _exception_base: _exception_pprint
652 658 }
653 659
654 660 #: printers for types specified by name
655 661 _deferred_type_pprinters = {
656 662 }
657 663
658 664 def for_type(typ, func):
659 665 """
660 666 Add a pretty printer for a given type.
661 667 """
662 668 oldfunc = _type_pprinters.get(typ, None)
663 669 if func is not None:
664 670 # To support easy restoration of old pprinters, we need to ignore Nones.
665 671 _type_pprinters[typ] = func
666 672 return oldfunc
667 673
668 674 def for_type_by_name(type_module, type_name, func):
669 675 """
670 676 Add a pretty printer for a type specified by the module and name of a type
671 677 rather than the type object itself.
672 678 """
673 679 key = (type_module, type_name)
674 680 oldfunc = _deferred_type_pprinters.get(key, None)
675 681 if func is not None:
676 682 # To support easy restoration of old pprinters, we need to ignore Nones.
677 683 _deferred_type_pprinters[key] = func
678 684 return oldfunc
679 685
680 686
681 687 #: printers for the default singletons
682 688 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
683 689 NotImplemented]), _repr_pprint)
684 690
685 691
686 692 if __name__ == '__main__':
687 693 from random import randrange
688 694 class Foo(object):
689 695 def __init__(self):
690 696 self.foo = 1
691 697 self.bar = re.compile(r'\s+')
692 698 self.blub = dict.fromkeys(range(30), randrange(1, 40))
693 699 self.hehe = 23424.234234
694 700 self.list = ["blub", "blah", self]
695 701
696 702 def get_foo(self):
697 703 print "foo"
698 704
699 705 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now