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