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