##// END OF EJS Templates
Remove unnecessary code checking for __repr__ on a subclass of builtin types...
Thomas Kluyver -
Show More
@@ -1,875 +1,860 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 395 if cls is not object \
396 396 and callable(cls.__dict__.get('__repr__')):
397 397 return _repr_pprint(obj, self, cycle)
398 398
399 399 return _default_pprint(obj, self, cycle)
400 400 finally:
401 401 self.end_group()
402 402 self.stack.pop()
403 403
404 404 def _in_deferred_types(self, cls):
405 405 """
406 406 Check if the given class is specified in the deferred type registry.
407 407
408 408 Returns the printer from the registry if it exists, and None if the
409 409 class is not in the registry. Successful matches will be moved to the
410 410 regular type registry for future use.
411 411 """
412 412 mod = _safe_getattr(cls, '__module__', None)
413 413 name = _safe_getattr(cls, '__name__', None)
414 414 key = (mod, name)
415 415 printer = None
416 416 if key in self.deferred_pprinters:
417 417 # Move the printer over to the regular registry.
418 418 printer = self.deferred_pprinters.pop(key)
419 419 self.type_pprinters[cls] = printer
420 420 return printer
421 421
422 422
423 423 class Printable(object):
424 424
425 425 def output(self, stream, output_width):
426 426 return output_width
427 427
428 428
429 429 class Text(Printable):
430 430
431 431 def __init__(self):
432 432 self.objs = []
433 433 self.width = 0
434 434
435 435 def output(self, stream, output_width):
436 436 for obj in self.objs:
437 437 stream.write(obj)
438 438 return output_width + self.width
439 439
440 440 def add(self, obj, width):
441 441 self.objs.append(obj)
442 442 self.width += width
443 443
444 444
445 445 class Breakable(Printable):
446 446
447 447 def __init__(self, seq, width, pretty):
448 448 self.obj = seq
449 449 self.width = width
450 450 self.pretty = pretty
451 451 self.indentation = pretty.indentation
452 452 self.group = pretty.group_stack[-1]
453 453 self.group.breakables.append(self)
454 454
455 455 def output(self, stream, output_width):
456 456 self.group.breakables.popleft()
457 457 if self.group.want_break:
458 458 stream.write(self.pretty.newline)
459 459 stream.write(' ' * self.indentation)
460 460 return self.indentation
461 461 if not self.group.breakables:
462 462 self.pretty.group_queue.remove(self.group)
463 463 stream.write(self.obj)
464 464 return output_width + self.width
465 465
466 466
467 467 class Group(Printable):
468 468
469 469 def __init__(self, depth):
470 470 self.depth = depth
471 471 self.breakables = deque()
472 472 self.want_break = False
473 473
474 474
475 475 class GroupQueue(object):
476 476
477 477 def __init__(self, *groups):
478 478 self.queue = []
479 479 for group in groups:
480 480 self.enq(group)
481 481
482 482 def enq(self, group):
483 483 depth = group.depth
484 484 while depth > len(self.queue) - 1:
485 485 self.queue.append([])
486 486 self.queue[depth].append(group)
487 487
488 488 def deq(self):
489 489 for stack in self.queue:
490 490 for idx, group in enumerate(reversed(stack)):
491 491 if group.breakables:
492 492 del stack[idx]
493 493 group.want_break = True
494 494 return group
495 495 for group in stack:
496 496 group.want_break = True
497 497 del stack[:]
498 498
499 499 def remove(self, group):
500 500 try:
501 501 self.queue[group.depth].remove(group)
502 502 except ValueError:
503 503 pass
504 504
505 505
506 506 def _default_pprint(obj, p, cycle):
507 507 """
508 508 The default print function. Used if an object does not provide one and
509 509 it's none of the builtin objects.
510 510 """
511 511 klass = _safe_getattr(obj, '__class__', None) or type(obj)
512 512 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
513 513 # A user-provided repr. Find newlines and replace them with p.break_()
514 514 _repr_pprint(obj, p, cycle)
515 515 return
516 516 p.begin_group(1, '<')
517 517 p.pretty(klass)
518 518 p.text(' at 0x%x' % id(obj))
519 519 if cycle:
520 520 p.text(' ...')
521 521 elif p.verbose:
522 522 first = True
523 523 for key in dir(obj):
524 524 if not key.startswith('_'):
525 525 try:
526 526 value = getattr(obj, key)
527 527 except AttributeError:
528 528 continue
529 529 if isinstance(value, types.MethodType):
530 530 continue
531 531 if not first:
532 532 p.text(',')
533 533 p.breakable()
534 534 p.text(key)
535 535 p.text('=')
536 536 step = len(key) + 1
537 537 p.indentation += step
538 538 p.pretty(value)
539 539 p.indentation -= step
540 540 first = False
541 541 p.end_group(1, '>')
542 542
543 543
544 def _seq_pprinter_factory(start, end, basetype):
544 def _seq_pprinter_factory(start, end):
545 545 """
546 546 Factory that returns a pprint function useful for sequences. Used by
547 547 the default pprint for tuples, dicts, and lists.
548 548 """
549 549 def inner(obj, p, cycle):
550 typ = type(obj)
551 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
552 # If the subclass provides its own repr, use it instead.
553 return p.text(typ.__repr__(obj))
554
555 550 if cycle:
556 551 return p.text(start + '...' + end)
557 552 step = len(start)
558 553 p.begin_group(step, start)
559 554 for idx, x in p._enumerate(obj):
560 555 if idx:
561 556 p.text(',')
562 557 p.breakable()
563 558 p.pretty(x)
564 559 if len(obj) == 1 and type(obj) is tuple:
565 560 # Special case for 1-item tuples.
566 561 p.text(',')
567 562 p.end_group(step, end)
568 563 return inner
569 564
570 565
571 def _set_pprinter_factory(start, end, basetype):
566 def _set_pprinter_factory(start, end):
572 567 """
573 568 Factory that returns a pprint function useful for sets and frozensets.
574 569 """
575 570 def inner(obj, p, cycle):
576 typ = type(obj)
577 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
578 # If the subclass provides its own repr, use it instead.
579 return p.text(typ.__repr__(obj))
580
581 571 if cycle:
582 572 return p.text(start + '...' + end)
583 573 if len(obj) == 0:
584 574 # Special case.
585 p.text(basetype.__name__ + '()')
575 p.text(type(obj).__name__ + '()')
586 576 else:
587 577 step = len(start)
588 578 p.begin_group(step, start)
589 579 # Like dictionary keys, we will try to sort the items if there aren't too many
590 580 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
591 581 items = _sorted_for_pprint(obj)
592 582 else:
593 583 items = obj
594 584 for idx, x in p._enumerate(items):
595 585 if idx:
596 586 p.text(',')
597 587 p.breakable()
598 588 p.pretty(x)
599 589 p.end_group(step, end)
600 590 return inner
601 591
602 592
603 def _dict_pprinter_factory(start, end, basetype=None):
593 def _dict_pprinter_factory(start, end):
604 594 """
605 595 Factory that returns a pprint function used by the default pprint of
606 596 dicts and dict proxies.
607 597 """
608 598 def inner(obj, p, cycle):
609 typ = type(obj)
610 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
611 # If the subclass provides its own repr, use it instead.
612 return p.text(typ.__repr__(obj))
613
614 599 if cycle:
615 600 return p.text('{...}')
616 601 step = len(start)
617 602 p.begin_group(step, start)
618 603 keys = obj.keys()
619 604 # if dict isn't large enough to be truncated, sort keys before displaying
620 605 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
621 606 keys = _sorted_for_pprint(keys)
622 607 for idx, key in p._enumerate(keys):
623 608 if idx:
624 609 p.text(',')
625 610 p.breakable()
626 611 p.pretty(key)
627 612 p.text(': ')
628 613 p.pretty(obj[key])
629 614 p.end_group(step, end)
630 615 return inner
631 616
632 617
633 618 def _super_pprint(obj, p, cycle):
634 619 """The pprint for the super type."""
635 620 p.begin_group(8, '<super: ')
636 621 p.pretty(obj.__thisclass__)
637 622 p.text(',')
638 623 p.breakable()
639 624 if PYPY: # In PyPy, super() objects don't have __self__ attributes
640 625 dself = obj.__repr__.__self__
641 626 p.pretty(None if dself is obj else dself)
642 627 else:
643 628 p.pretty(obj.__self__)
644 629 p.end_group(8, '>')
645 630
646 631
647 632 def _re_pattern_pprint(obj, p, cycle):
648 633 """The pprint function for regular expression patterns."""
649 634 p.text('re.compile(')
650 635 pattern = repr(obj.pattern)
651 636 if pattern[:1] in 'uU':
652 637 pattern = pattern[1:]
653 638 prefix = 'ur'
654 639 else:
655 640 prefix = 'r'
656 641 pattern = prefix + pattern.replace('\\\\', '\\')
657 642 p.text(pattern)
658 643 if obj.flags:
659 644 p.text(',')
660 645 p.breakable()
661 646 done_one = False
662 647 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
663 648 'UNICODE', 'VERBOSE', 'DEBUG'):
664 649 if obj.flags & getattr(re, flag):
665 650 if done_one:
666 651 p.text('|')
667 652 p.text('re.' + flag)
668 653 done_one = True
669 654 p.text(')')
670 655
671 656
672 657 def _type_pprint(obj, p, cycle):
673 658 """The pprint for classes and types."""
674 659 # Heap allocated types might not have the module attribute,
675 660 # and others may set it to None.
676 661
677 662 # Checks for a __repr__ override in the metaclass. Can't compare the
678 663 # type(obj).__repr__ directly because in PyPy the representation function
679 664 # inherited from type isn't the same type.__repr__
680 665 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
681 666 _repr_pprint(obj, p, cycle)
682 667 return
683 668
684 669 mod = _safe_getattr(obj, '__module__', None)
685 670 try:
686 671 name = obj.__qualname__
687 672 if not isinstance(name, str):
688 673 # This can happen if the type implements __qualname__ as a property
689 674 # or other descriptor in Python 2.
690 675 raise Exception("Try __name__")
691 676 except Exception:
692 677 name = obj.__name__
693 678 if not isinstance(name, str):
694 679 name = '<unknown type>'
695 680
696 681 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
697 682 p.text(name)
698 683 else:
699 684 p.text(mod + '.' + name)
700 685
701 686
702 687 def _repr_pprint(obj, p, cycle):
703 688 """A pprint that just redirects to the normal repr function."""
704 689 # Find newlines and replace them with p.break_()
705 690 output = repr(obj)
706 691 for idx,output_line in enumerate(output.splitlines()):
707 692 if idx:
708 693 p.break_()
709 694 p.text(output_line)
710 695
711 696
712 697 def _function_pprint(obj, p, cycle):
713 698 """Base pprint for all functions and builtin functions."""
714 699 name = _safe_getattr(obj, '__qualname__', obj.__name__)
715 700 mod = obj.__module__
716 701 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
717 702 name = mod + '.' + name
718 703 try:
719 704 func_def = name + str(signature(obj))
720 705 except ValueError:
721 706 func_def = name
722 707 p.text('<function %s>' % func_def)
723 708
724 709
725 710 def _exception_pprint(obj, p, cycle):
726 711 """Base pprint for all exceptions."""
727 712 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
728 713 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
729 714 name = '%s.%s' % (obj.__class__.__module__, name)
730 715 step = len(name) + 1
731 716 p.begin_group(step, name + '(')
732 717 for idx, arg in enumerate(getattr(obj, 'args', ())):
733 718 if idx:
734 719 p.text(',')
735 720 p.breakable()
736 721 p.pretty(arg)
737 722 p.end_group(step, ')')
738 723
739 724
740 725 #: the exception base
741 726 try:
742 727 _exception_base = BaseException
743 728 except NameError:
744 729 _exception_base = Exception
745 730
746 731
747 732 #: printers for builtin types
748 733 _type_pprinters = {
749 734 int: _repr_pprint,
750 735 float: _repr_pprint,
751 736 str: _repr_pprint,
752 tuple: _seq_pprinter_factory('(', ')', tuple),
753 list: _seq_pprinter_factory('[', ']', list),
754 dict: _dict_pprinter_factory('{', '}', dict),
737 tuple: _seq_pprinter_factory('(', ')'),
738 list: _seq_pprinter_factory('[', ']'),
739 dict: _dict_pprinter_factory('{', '}'),
755 740
756 set: _set_pprinter_factory('{', '}', set),
757 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
741 set: _set_pprinter_factory('{', '}'),
742 frozenset: _set_pprinter_factory('frozenset({', '})'),
758 743 super: _super_pprint,
759 744 _re_pattern_type: _re_pattern_pprint,
760 745 type: _type_pprint,
761 746 types.FunctionType: _function_pprint,
762 747 types.BuiltinFunctionType: _function_pprint,
763 748 types.MethodType: _repr_pprint,
764 749
765 750 datetime.datetime: _repr_pprint,
766 751 datetime.timedelta: _repr_pprint,
767 752 _exception_base: _exception_pprint
768 753 }
769 754
770 755 try:
771 756 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
772 757 # using dict.setdefault avoids overwritting the dict printer
773 758 _type_pprinters.setdefault(types.DictProxyType,
774 759 _dict_pprinter_factory('dict_proxy({', '})'))
775 760 _type_pprinters[types.ClassType] = _type_pprint
776 761 _type_pprinters[types.SliceType] = _repr_pprint
777 762 except AttributeError: # Python 3
778 763 _type_pprinters[types.MappingProxyType] = \
779 764 _dict_pprinter_factory('mappingproxy({', '})')
780 765 _type_pprinters[slice] = _repr_pprint
781 766
782 767 try:
783 768 _type_pprinters[long] = _repr_pprint
784 769 _type_pprinters[unicode] = _repr_pprint
785 770 except NameError:
786 771 _type_pprinters[range] = _repr_pprint
787 772 _type_pprinters[bytes] = _repr_pprint
788 773
789 774 #: printers for types specified by name
790 775 _deferred_type_pprinters = {
791 776 }
792 777
793 778 def for_type(typ, func):
794 779 """
795 780 Add a pretty printer for a given type.
796 781 """
797 782 oldfunc = _type_pprinters.get(typ, None)
798 783 if func is not None:
799 784 # To support easy restoration of old pprinters, we need to ignore Nones.
800 785 _type_pprinters[typ] = func
801 786 return oldfunc
802 787
803 788 def for_type_by_name(type_module, type_name, func):
804 789 """
805 790 Add a pretty printer for a type specified by the module and name of a type
806 791 rather than the type object itself.
807 792 """
808 793 key = (type_module, type_name)
809 794 oldfunc = _deferred_type_pprinters.get(key, None)
810 795 if func is not None:
811 796 # To support easy restoration of old pprinters, we need to ignore Nones.
812 797 _deferred_type_pprinters[key] = func
813 798 return oldfunc
814 799
815 800
816 801 #: printers for the default singletons
817 802 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
818 803 NotImplemented]), _repr_pprint)
819 804
820 805
821 806 def _defaultdict_pprint(obj, p, cycle):
822 807 name = obj.__class__.__name__
823 808 with p.group(len(name) + 1, name + '(', ')'):
824 809 if cycle:
825 810 p.text('...')
826 811 else:
827 812 p.pretty(obj.default_factory)
828 813 p.text(',')
829 814 p.breakable()
830 815 p.pretty(dict(obj))
831 816
832 817 def _ordereddict_pprint(obj, p, cycle):
833 818 name = obj.__class__.__name__
834 819 with p.group(len(name) + 1, name + '(', ')'):
835 820 if cycle:
836 821 p.text('...')
837 822 elif len(obj):
838 823 p.pretty(list(obj.items()))
839 824
840 825 def _deque_pprint(obj, p, cycle):
841 826 name = obj.__class__.__name__
842 827 with p.group(len(name) + 1, name + '(', ')'):
843 828 if cycle:
844 829 p.text('...')
845 830 else:
846 831 p.pretty(list(obj))
847 832
848 833
849 834 def _counter_pprint(obj, p, cycle):
850 835 name = obj.__class__.__name__
851 836 with p.group(len(name) + 1, name + '(', ')'):
852 837 if cycle:
853 838 p.text('...')
854 839 elif len(obj):
855 840 p.pretty(dict(obj))
856 841
857 842 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
858 843 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
859 844 for_type_by_name('collections', 'deque', _deque_pprint)
860 845 for_type_by_name('collections', 'Counter', _counter_pprint)
861 846
862 847 if __name__ == '__main__':
863 848 from random import randrange
864 849 class Foo(object):
865 850 def __init__(self):
866 851 self.foo = 1
867 852 self.bar = re.compile(r'\s+')
868 853 self.blub = dict.fromkeys(range(30), randrange(1, 40))
869 854 self.hehe = 23424.234234
870 855 self.list = ["blub", "blah", self]
871 856
872 857 def get_foo(self):
873 858 print("foo")
874 859
875 860 pprint(Foo(), verbose=True)
@@ -1,437 +1,443 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 424
425 425 class OrderedCounter(Counter, OrderedDict):
426 426 'Counter that remembers the order elements are first encountered'
427 427
428 428 def __repr__(self):
429 429 return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
430 430
431 431 def __reduce__(self):
432 432 return self.__class__, (OrderedDict(self),)
433 433
434 class MySet(set): # Override repr of a basic type
435 def __repr__(self):
436 return 'mine'
437
434 438 def test_custom_repr():
435 439 """A custom repr should override a pretty printer for a parent type"""
436 440 oc = OrderedCounter("abracadabra")
437 441 nt.assert_in("OrderedCounter(OrderedDict", pretty.pretty(oc))
442
443 nt.assert_equal(pretty.pretty(MySet()), 'mine')
General Comments 0
You need to be logged in to leave comments. Login now