##// END OF EJS Templates
Merge pull request #5376 from minrk/pretty-cap...
Paul Ivanov -
r15866:11575ed2 merge
parent child Browse files
Show More
@@ -1,851 +1,862 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 print_function
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 collections import deque
113 113
114 114 from IPython.utils.py3compat import PY3
115 115
116 116 if PY3:
117 117 from io import StringIO
118 118 else:
119 119 from StringIO import StringIO
120 120
121 121
122 122 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
123 123 'for_type', 'for_type_by_name']
124 124
125 125
126 126 _re_pattern_type = type(re.compile(''))
127 127
128 128 def _failed_repr(obj, e):
129 129 """Render a failed repr, including the exception.
130 130
131 131 Tries to get exception and type info
132 132 """
133 133 # get exception name
134 134 if e.__class__.__module__ in ('exceptions', 'builtins'):
135 135 ename = e.__class__.__name__
136 136 else:
137 137 ename = '{}.{}'.format(
138 138 e.__class__.__module__,
139 139 e.__class__.__name__,
140 140 )
141 141 # and exception string, which sometimes fails
142 142 # (usually due to unicode error message)
143 143 try:
144 144 estr = str(e)
145 145 except Exception:
146 146 estr = "unknown"
147 147
148 148 # and class name
149 149 try:
150 150 klass = _safe_getattr(obj, '__class__', None) or type(obj)
151 151 mod = _safe_getattr(klass, '__module__', None)
152 152 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
153 153 classname = klass.__name__
154 154 else:
155 155 classname = mod + '.' + klass.__name__
156 156 except Exception:
157 157 # this may be paranoid, but we already know repr is broken
158 158 classname = "unknown type"
159 159
160 160 # the informative repr
161 161 return "<repr(<{} at 0x{:x}>) failed: {}: {}>".format(
162 162 classname, id(obj), ename, estr,
163 163 )
164 164
165 165 def _safe_repr(obj):
166 166 """Don't assume repr is not broken."""
167 167 try:
168 168 return repr(obj)
169 169 except Exception as e:
170 170 return _failed_repr(obj, e)
171 171
172 172 def _safe_getattr(obj, attr, default=None):
173 173 """Safe version of getattr.
174 174
175 175 Same as getattr, but will return ``default`` on any Exception,
176 176 rather than raising.
177 177 """
178 178 try:
179 179 return getattr(obj, attr, default)
180 180 except Exception:
181 181 return default
182 182
183 183 def pretty(obj, verbose=False, max_width=79, newline='\n'):
184 184 """
185 185 Pretty print the object's representation.
186 186 """
187 187 stream = StringIO()
188 188 printer = RepresentationPrinter(stream, verbose, max_width, newline)
189 189 printer.pretty(obj)
190 190 printer.flush()
191 191 return stream.getvalue()
192 192
193 193
194 194 def pprint(obj, verbose=False, max_width=79, newline='\n'):
195 195 """
196 196 Like `pretty` but print to stdout.
197 197 """
198 198 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
199 199 printer.pretty(obj)
200 200 printer.flush()
201 201 sys.stdout.write(newline)
202 202 sys.stdout.flush()
203 203
204 204 class _PrettyPrinterBase(object):
205 205
206 206 @contextmanager
207 207 def indent(self, indent):
208 208 """with statement support for indenting/dedenting."""
209 209 self.indentation += indent
210 210 try:
211 211 yield
212 212 finally:
213 213 self.indentation -= indent
214 214
215 215 @contextmanager
216 216 def group(self, indent=0, open='', close=''):
217 217 """like begin_group / end_group but for the with statement."""
218 218 self.begin_group(indent, open)
219 219 try:
220 220 yield
221 221 finally:
222 222 self.end_group(indent, close)
223 223
224 224 class PrettyPrinter(_PrettyPrinterBase):
225 225 """
226 226 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
227 227 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
228 228 this printer knows nothing about the default pprinters or the `_repr_pretty_`
229 229 callback method.
230 230 """
231 231
232 def __init__(self, output, max_width=79, newline='\n'):
232 def __init__(self, output, max_width=79, newline='\n', max_seq_length=1000):
233 233 self.output = output
234 234 self.max_width = max_width
235 235 self.newline = newline
236 self.max_seq_length = max_seq_length
236 237 self.output_width = 0
237 238 self.buffer_width = 0
238 239 self.buffer = deque()
239 240
240 241 root_group = Group(0)
241 242 self.group_stack = [root_group]
242 243 self.group_queue = GroupQueue(root_group)
243 244 self.indentation = 0
244 245
245 246 def _break_outer_groups(self):
246 247 while self.max_width < self.output_width + self.buffer_width:
247 248 group = self.group_queue.deq()
248 249 if not group:
249 250 return
250 251 while group.breakables:
251 252 x = self.buffer.popleft()
252 253 self.output_width = x.output(self.output, self.output_width)
253 254 self.buffer_width -= x.width
254 255 while self.buffer and isinstance(self.buffer[0], Text):
255 256 x = self.buffer.popleft()
256 257 self.output_width = x.output(self.output, self.output_width)
257 258 self.buffer_width -= x.width
258 259
259 260 def text(self, obj):
260 261 """Add literal text to the output."""
261 262 width = len(obj)
262 263 if self.buffer:
263 264 text = self.buffer[-1]
264 265 if not isinstance(text, Text):
265 266 text = Text()
266 267 self.buffer.append(text)
267 268 text.add(obj, width)
268 269 self.buffer_width += width
269 270 self._break_outer_groups()
270 271 else:
271 272 self.output.write(obj)
272 273 self.output_width += width
273 274
274 275 def breakable(self, sep=' '):
275 276 """
276 277 Add a breakable separator to the output. This does not mean that it
277 278 will automatically break here. If no breaking on this position takes
278 279 place the `sep` is inserted which default to one space.
279 280 """
280 281 width = len(sep)
281 282 group = self.group_stack[-1]
282 283 if group.want_break:
283 284 self.flush()
284 285 self.output.write(self.newline)
285 286 self.output.write(' ' * self.indentation)
286 287 self.output_width = self.indentation
287 288 self.buffer_width = 0
288 289 else:
289 290 self.buffer.append(Breakable(sep, width, self))
290 291 self.buffer_width += width
291 292 self._break_outer_groups()
292 293
293 294 def break_(self):
294 295 """
295 296 Explicitly insert a newline into the output, maintaining correct indentation.
296 297 """
297 298 self.flush()
298 299 self.output.write(self.newline)
299 300 self.output.write(' ' * self.indentation)
300 301 self.output_width = self.indentation
301 302 self.buffer_width = 0
302 303
303 304
304 305 def begin_group(self, indent=0, open=''):
305 306 """
306 307 Begin a group. If you want support for python < 2.5 which doesn't has
307 308 the with statement this is the preferred way:
308 309
309 310 p.begin_group(1, '{')
310 311 ...
311 312 p.end_group(1, '}')
312 313
313 314 The python 2.5 expression would be this:
314 315
315 316 with p.group(1, '{', '}'):
316 317 ...
317 318
318 319 The first parameter specifies the indentation for the next line (usually
319 320 the width of the opening text), the second the opening text. All
320 321 parameters are optional.
321 322 """
322 323 if open:
323 324 self.text(open)
324 325 group = Group(self.group_stack[-1].depth + 1)
325 326 self.group_stack.append(group)
326 327 self.group_queue.enq(group)
327 328 self.indentation += indent
328
329
330 def _enumerate(self, seq):
331 """like enumerate, but with an upper limit on the number of items"""
332 for idx, x in enumerate(seq):
333 if self.max_seq_length and idx >= self.max_seq_length:
334 self.text(',')
335 self.breakable()
336 self.text('...')
337 raise StopIteration
338 yield idx, x
339
329 340 def end_group(self, dedent=0, close=''):
330 341 """End a group. See `begin_group` for more details."""
331 342 self.indentation -= dedent
332 343 group = self.group_stack.pop()
333 344 if not group.breakables:
334 345 self.group_queue.remove(group)
335 346 if close:
336 347 self.text(close)
337 348
338 349 def flush(self):
339 350 """Flush data that is left in the buffer."""
340 351 for data in self.buffer:
341 352 self.output_width += data.output(self.output, self.output_width)
342 353 self.buffer.clear()
343 354 self.buffer_width = 0
344 355
345 356
346 357 def _get_mro(obj_class):
347 358 """ Get a reasonable method resolution order of a class and its superclasses
348 359 for both old-style and new-style classes.
349 360 """
350 361 if not hasattr(obj_class, '__mro__'):
351 362 # Old-style class. Mix in object to make a fake new-style class.
352 363 try:
353 364 obj_class = type(obj_class.__name__, (obj_class, object), {})
354 365 except TypeError:
355 366 # Old-style extension type that does not descend from object.
356 367 # FIXME: try to construct a more thorough MRO.
357 368 mro = [obj_class]
358 369 else:
359 370 mro = obj_class.__mro__[1:-1]
360 371 else:
361 372 mro = obj_class.__mro__
362 373 return mro
363 374
364 375
365 376 class RepresentationPrinter(PrettyPrinter):
366 377 """
367 378 Special pretty printer that has a `pretty` method that calls the pretty
368 379 printer for a python object.
369 380
370 381 This class stores processing data on `self` so you must *never* use
371 382 this class in a threaded environment. Always lock it or reinstanciate
372 383 it.
373 384
374 385 Instances also have a verbose flag callbacks can access to control their
375 386 output. For example the default instance repr prints all attributes and
376 387 methods that are not prefixed by an underscore if the printer is in
377 388 verbose mode.
378 389 """
379 390
380 391 def __init__(self, output, verbose=False, max_width=79, newline='\n',
381 392 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
382 393
383 394 PrettyPrinter.__init__(self, output, max_width, newline)
384 395 self.verbose = verbose
385 396 self.stack = []
386 397 if singleton_pprinters is None:
387 398 singleton_pprinters = _singleton_pprinters.copy()
388 399 self.singleton_pprinters = singleton_pprinters
389 400 if type_pprinters is None:
390 401 type_pprinters = _type_pprinters.copy()
391 402 self.type_pprinters = type_pprinters
392 403 if deferred_pprinters is None:
393 404 deferred_pprinters = _deferred_type_pprinters.copy()
394 405 self.deferred_pprinters = deferred_pprinters
395 406
396 407 def pretty(self, obj):
397 408 """Pretty print the given object."""
398 409 obj_id = id(obj)
399 410 cycle = obj_id in self.stack
400 411 self.stack.append(obj_id)
401 412 self.begin_group()
402 413 try:
403 414 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
404 415 # First try to find registered singleton printers for the type.
405 416 try:
406 417 printer = self.singleton_pprinters[obj_id]
407 418 except (TypeError, KeyError):
408 419 pass
409 420 else:
410 421 return printer(obj, self, cycle)
411 422 # Next walk the mro and check for either:
412 423 # 1) a registered printer
413 424 # 2) a _repr_pretty_ method
414 425 for cls in _get_mro(obj_class):
415 426 if cls in self.type_pprinters:
416 427 # printer registered in self.type_pprinters
417 428 return self.type_pprinters[cls](obj, self, cycle)
418 429 else:
419 430 # deferred printer
420 431 printer = self._in_deferred_types(cls)
421 432 if printer is not None:
422 433 return printer(obj, self, cycle)
423 434 else:
424 435 # Finally look for special method names.
425 436 # Some objects automatically create any requested
426 437 # attribute. Try to ignore most of them by checking for
427 438 # callability.
428 439 if '_repr_pretty_' in cls.__dict__:
429 440 meth = cls._repr_pretty_
430 441 if callable(meth):
431 442 return meth(obj, self, cycle)
432 443 return _default_pprint(obj, self, cycle)
433 444 finally:
434 445 self.end_group()
435 446 self.stack.pop()
436 447
437 448 def _in_deferred_types(self, cls):
438 449 """
439 450 Check if the given class is specified in the deferred type registry.
440 451
441 452 Returns the printer from the registry if it exists, and None if the
442 453 class is not in the registry. Successful matches will be moved to the
443 454 regular type registry for future use.
444 455 """
445 456 mod = _safe_getattr(cls, '__module__', None)
446 457 name = _safe_getattr(cls, '__name__', None)
447 458 key = (mod, name)
448 459 printer = None
449 460 if key in self.deferred_pprinters:
450 461 # Move the printer over to the regular registry.
451 462 printer = self.deferred_pprinters.pop(key)
452 463 self.type_pprinters[cls] = printer
453 464 return printer
454 465
455 466
456 467 class Printable(object):
457 468
458 469 def output(self, stream, output_width):
459 470 return output_width
460 471
461 472
462 473 class Text(Printable):
463 474
464 475 def __init__(self):
465 476 self.objs = []
466 477 self.width = 0
467 478
468 479 def output(self, stream, output_width):
469 480 for obj in self.objs:
470 481 stream.write(obj)
471 482 return output_width + self.width
472 483
473 484 def add(self, obj, width):
474 485 self.objs.append(obj)
475 486 self.width += width
476 487
477 488
478 489 class Breakable(Printable):
479 490
480 491 def __init__(self, seq, width, pretty):
481 492 self.obj = seq
482 493 self.width = width
483 494 self.pretty = pretty
484 495 self.indentation = pretty.indentation
485 496 self.group = pretty.group_stack[-1]
486 497 self.group.breakables.append(self)
487 498
488 499 def output(self, stream, output_width):
489 500 self.group.breakables.popleft()
490 501 if self.group.want_break:
491 502 stream.write(self.pretty.newline)
492 503 stream.write(' ' * self.indentation)
493 504 return self.indentation
494 505 if not self.group.breakables:
495 506 self.pretty.group_queue.remove(self.group)
496 507 stream.write(self.obj)
497 508 return output_width + self.width
498 509
499 510
500 511 class Group(Printable):
501 512
502 513 def __init__(self, depth):
503 514 self.depth = depth
504 515 self.breakables = deque()
505 516 self.want_break = False
506 517
507 518
508 519 class GroupQueue(object):
509 520
510 521 def __init__(self, *groups):
511 522 self.queue = []
512 523 for group in groups:
513 524 self.enq(group)
514 525
515 526 def enq(self, group):
516 527 depth = group.depth
517 528 while depth > len(self.queue) - 1:
518 529 self.queue.append([])
519 530 self.queue[depth].append(group)
520 531
521 532 def deq(self):
522 533 for stack in self.queue:
523 534 for idx, group in enumerate(reversed(stack)):
524 535 if group.breakables:
525 536 del stack[idx]
526 537 group.want_break = True
527 538 return group
528 539 for group in stack:
529 540 group.want_break = True
530 541 del stack[:]
531 542
532 543 def remove(self, group):
533 544 try:
534 545 self.queue[group.depth].remove(group)
535 546 except ValueError:
536 547 pass
537 548
538 549 try:
539 550 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
540 551 except AttributeError: # Python 3
541 552 _baseclass_reprs = (object.__repr__,)
542 553
543 554
544 555 def _default_pprint(obj, p, cycle):
545 556 """
546 557 The default print function. Used if an object does not provide one and
547 558 it's none of the builtin objects.
548 559 """
549 560 klass = _safe_getattr(obj, '__class__', None) or type(obj)
550 561 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
551 562 # A user-provided repr. Find newlines and replace them with p.break_()
552 563 output = _safe_repr(obj)
553 564 for idx,output_line in enumerate(output.splitlines()):
554 565 if idx:
555 566 p.break_()
556 567 p.text(output_line)
557 568 return
558 569 p.begin_group(1, '<')
559 570 p.pretty(klass)
560 571 p.text(' at 0x%x' % id(obj))
561 572 if cycle:
562 573 p.text(' ...')
563 574 elif p.verbose:
564 575 first = True
565 576 for key in dir(obj):
566 577 if not key.startswith('_'):
567 578 try:
568 579 value = getattr(obj, key)
569 580 except AttributeError:
570 581 continue
571 582 if isinstance(value, types.MethodType):
572 583 continue
573 584 if not first:
574 585 p.text(',')
575 586 p.breakable()
576 587 p.text(key)
577 588 p.text('=')
578 589 step = len(key) + 1
579 590 p.indentation += step
580 591 p.pretty(value)
581 592 p.indentation -= step
582 593 first = False
583 594 p.end_group(1, '>')
584 595
585 596
586 597 def _seq_pprinter_factory(start, end, basetype):
587 598 """
588 599 Factory that returns a pprint function useful for sequences. Used by
589 600 the default pprint for tuples, dicts, and lists.
590 601 """
591 602 def inner(obj, p, cycle):
592 603 typ = type(obj)
593 604 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
594 605 # If the subclass provides its own repr, use it instead.
595 606 return p.text(typ.__repr__(obj))
596 607
597 608 if cycle:
598 609 return p.text(start + '...' + end)
599 610 step = len(start)
600 611 p.begin_group(step, start)
601 for idx, x in enumerate(obj):
612 for idx, x in p._enumerate(obj):
602 613 if idx:
603 614 p.text(',')
604 615 p.breakable()
605 616 p.pretty(x)
606 617 if len(obj) == 1 and type(obj) is tuple:
607 618 # Special case for 1-item tuples.
608 619 p.text(',')
609 620 p.end_group(step, end)
610 621 return inner
611 622
612 623
613 624 def _set_pprinter_factory(start, end, basetype):
614 625 """
615 626 Factory that returns a pprint function useful for sets and frozensets.
616 627 """
617 628 def inner(obj, p, cycle):
618 629 typ = type(obj)
619 630 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
620 631 # If the subclass provides its own repr, use it instead.
621 632 return p.text(typ.__repr__(obj))
622 633
623 634 if cycle:
624 635 return p.text(start + '...' + end)
625 636 if len(obj) == 0:
626 637 # Special case.
627 638 p.text(basetype.__name__ + '()')
628 639 else:
629 640 step = len(start)
630 641 p.begin_group(step, start)
631 642 # Like dictionary keys, we will try to sort the items.
632 643 items = list(obj)
633 644 try:
634 645 items.sort()
635 646 except Exception:
636 647 # Sometimes the items don't sort.
637 648 pass
638 for idx, x in enumerate(items):
649 for idx, x in p._enumerate(items):
639 650 if idx:
640 651 p.text(',')
641 652 p.breakable()
642 653 p.pretty(x)
643 654 p.end_group(step, end)
644 655 return inner
645 656
646 657
647 658 def _dict_pprinter_factory(start, end, basetype=None):
648 659 """
649 660 Factory that returns a pprint function used by the default pprint of
650 661 dicts and dict proxies.
651 662 """
652 663 def inner(obj, p, cycle):
653 664 typ = type(obj)
654 665 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
655 666 # If the subclass provides its own repr, use it instead.
656 667 return p.text(typ.__repr__(obj))
657 668
658 669 if cycle:
659 670 return p.text('{...}')
660 671 p.begin_group(1, start)
661 672 keys = obj.keys()
662 673 try:
663 674 keys.sort()
664 675 except Exception as e:
665 676 # Sometimes the keys don't sort.
666 677 pass
667 for idx, key in enumerate(keys):
678 for idx, key in p._enumerate(keys):
668 679 if idx:
669 680 p.text(',')
670 681 p.breakable()
671 682 p.pretty(key)
672 683 p.text(': ')
673 684 p.pretty(obj[key])
674 685 p.end_group(1, end)
675 686 return inner
676 687
677 688
678 689 def _super_pprint(obj, p, cycle):
679 690 """The pprint for the super type."""
680 691 p.begin_group(8, '<super: ')
681 692 p.pretty(obj.__thisclass__)
682 693 p.text(',')
683 694 p.breakable()
684 695 p.pretty(obj.__self__)
685 696 p.end_group(8, '>')
686 697
687 698
688 699 def _re_pattern_pprint(obj, p, cycle):
689 700 """The pprint function for regular expression patterns."""
690 701 p.text('re.compile(')
691 702 pattern = repr(obj.pattern)
692 703 if pattern[:1] in 'uU':
693 704 pattern = pattern[1:]
694 705 prefix = 'ur'
695 706 else:
696 707 prefix = 'r'
697 708 pattern = prefix + pattern.replace('\\\\', '\\')
698 709 p.text(pattern)
699 710 if obj.flags:
700 711 p.text(',')
701 712 p.breakable()
702 713 done_one = False
703 714 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
704 715 'UNICODE', 'VERBOSE', 'DEBUG'):
705 716 if obj.flags & getattr(re, flag):
706 717 if done_one:
707 718 p.text('|')
708 719 p.text('re.' + flag)
709 720 done_one = True
710 721 p.text(')')
711 722
712 723
713 724 def _type_pprint(obj, p, cycle):
714 725 """The pprint for classes and types."""
715 726 mod = _safe_getattr(obj, '__module__', None)
716 727 if mod is None:
717 728 # Heap allocated types might not have the module attribute,
718 729 # and others may set it to None.
719 730 return p.text(obj.__name__)
720 731
721 732 if mod in ('__builtin__', 'builtins', 'exceptions'):
722 733 name = obj.__name__
723 734 else:
724 735 name = mod + '.' + obj.__name__
725 736 p.text(name)
726 737
727 738
728 739 def _repr_pprint(obj, p, cycle):
729 740 """A pprint that just redirects to the normal repr function."""
730 741 p.text(_safe_repr(obj))
731 742
732 743
733 744 def _function_pprint(obj, p, cycle):
734 745 """Base pprint for all functions and builtin functions."""
735 746 if obj.__module__ in ('__builtin__', 'builtins', 'exceptions') or not obj.__module__:
736 747 name = obj.__name__
737 748 else:
738 749 name = obj.__module__ + '.' + obj.__name__
739 750 p.text('<function %s>' % name)
740 751
741 752
742 753 def _exception_pprint(obj, p, cycle):
743 754 """Base pprint for all exceptions."""
744 755 if obj.__class__.__module__ in ('exceptions', 'builtins'):
745 756 name = obj.__class__.__name__
746 757 else:
747 758 name = '%s.%s' % (
748 759 obj.__class__.__module__,
749 760 obj.__class__.__name__
750 761 )
751 762 step = len(name) + 1
752 763 p.begin_group(step, name + '(')
753 764 for idx, arg in enumerate(getattr(obj, 'args', ())):
754 765 if idx:
755 766 p.text(',')
756 767 p.breakable()
757 768 p.pretty(arg)
758 769 p.end_group(step, ')')
759 770
760 771
761 772 #: the exception base
762 773 try:
763 774 _exception_base = BaseException
764 775 except NameError:
765 776 _exception_base = Exception
766 777
767 778
768 779 #: printers for builtin types
769 780 _type_pprinters = {
770 781 int: _repr_pprint,
771 782 float: _repr_pprint,
772 783 str: _repr_pprint,
773 784 tuple: _seq_pprinter_factory('(', ')', tuple),
774 785 list: _seq_pprinter_factory('[', ']', list),
775 786 dict: _dict_pprinter_factory('{', '}', dict),
776 787
777 788 set: _set_pprinter_factory('{', '}', set),
778 789 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
779 790 super: _super_pprint,
780 791 _re_pattern_type: _re_pattern_pprint,
781 792 type: _type_pprint,
782 793 types.FunctionType: _function_pprint,
783 794 types.BuiltinFunctionType: _function_pprint,
784 795 types.MethodType: _repr_pprint,
785 796
786 797 datetime.datetime: _repr_pprint,
787 798 datetime.timedelta: _repr_pprint,
788 799 _exception_base: _exception_pprint
789 800 }
790 801
791 802 try:
792 803 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
793 804 _type_pprinters[types.ClassType] = _type_pprint
794 805 _type_pprinters[types.SliceType] = _repr_pprint
795 806 except AttributeError: # Python 3
796 807 _type_pprinters[slice] = _repr_pprint
797 808
798 809 try:
799 810 _type_pprinters[xrange] = _repr_pprint
800 811 _type_pprinters[long] = _repr_pprint
801 812 _type_pprinters[unicode] = _repr_pprint
802 813 except NameError:
803 814 _type_pprinters[range] = _repr_pprint
804 815 _type_pprinters[bytes] = _repr_pprint
805 816
806 817 #: printers for types specified by name
807 818 _deferred_type_pprinters = {
808 819 }
809 820
810 821 def for_type(typ, func):
811 822 """
812 823 Add a pretty printer for a given type.
813 824 """
814 825 oldfunc = _type_pprinters.get(typ, None)
815 826 if func is not None:
816 827 # To support easy restoration of old pprinters, we need to ignore Nones.
817 828 _type_pprinters[typ] = func
818 829 return oldfunc
819 830
820 831 def for_type_by_name(type_module, type_name, func):
821 832 """
822 833 Add a pretty printer for a type specified by the module and name of a type
823 834 rather than the type object itself.
824 835 """
825 836 key = (type_module, type_name)
826 837 oldfunc = _deferred_type_pprinters.get(key, None)
827 838 if func is not None:
828 839 # To support easy restoration of old pprinters, we need to ignore Nones.
829 840 _deferred_type_pprinters[key] = func
830 841 return oldfunc
831 842
832 843
833 844 #: printers for the default singletons
834 845 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
835 846 NotImplemented]), _repr_pprint)
836 847
837 848
838 849 if __name__ == '__main__':
839 850 from random import randrange
840 851 class Foo(object):
841 852 def __init__(self):
842 853 self.foo = 1
843 854 self.bar = re.compile(r'\s+')
844 855 self.blub = dict.fromkeys(range(30), randrange(1, 40))
845 856 self.hehe = 23424.234234
846 857 self.list = ["blub", "blah", self]
847 858
848 859 def get_foo(self):
849 860 print("foo")
850 861
851 862 pprint(Foo(), verbose=True)
@@ -1,199 +1,224 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 class NoModule(object):
57 57 pass
58 58
59 59 NoModule.__module__ = None
60 60
61 61 class Breaking(object):
62 62 def _repr_pretty_(self, p, cycle):
63 63 with p.group(4,"TG: ",":"):
64 64 p.text("Breaking(")
65 65 p.break_()
66 66 p.text(")")
67 67
68 68 class BreakingRepr(object):
69 69 def __repr__(self):
70 70 return "Breaking(\n)"
71 71
72 72 class BreakingReprParent(object):
73 73 def _repr_pretty_(self, p, cycle):
74 74 with p.group(4,"TG: ",":"):
75 75 p.pretty(BreakingRepr())
76 76
77 77 class BadRepr(object):
78 78
79 79 def __repr__(self):
80 80 return 1/0
81 81
82 82
83 83 def test_indentation():
84 84 """Test correct indentation in groups"""
85 85 count = 40
86 86 gotoutput = pretty.pretty(MyList(range(count)))
87 87 expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
88 88
89 89 nt.assert_equal(gotoutput, expectedoutput)
90 90
91 91
92 92 def test_dispatch():
93 93 """
94 94 Test correct dispatching: The _repr_pretty_ method for MyDict
95 95 must be found before the registered printer for dict.
96 96 """
97 97 gotoutput = pretty.pretty(MyDict())
98 98 expectedoutput = "MyDict(...)"
99 99
100 100 nt.assert_equal(gotoutput, expectedoutput)
101 101
102 102
103 103 def test_callability_checking():
104 104 """
105 105 Test that the _repr_pretty_ method is tested for callability and skipped if
106 106 not.
107 107 """
108 108 gotoutput = pretty.pretty(Dummy2())
109 109 expectedoutput = "Dummy1(...)"
110 110
111 111 nt.assert_equal(gotoutput, expectedoutput)
112 112
113 113
114 114 def test_sets():
115 115 """
116 116 Test that set and frozenset use Python 3 formatting.
117 117 """
118 118 objects = [set(), frozenset(), set([1]), frozenset([1]), set([1, 2]),
119 119 frozenset([1, 2]), set([-1, -2, -3])]
120 120 expected = ['set()', 'frozenset()', '{1}', 'frozenset({1})', '{1, 2}',
121 121 'frozenset({1, 2})', '{-3, -2, -1}']
122 122 for obj, expected_output in zip(objects, expected):
123 123 got_output = pretty.pretty(obj)
124 124 yield nt.assert_equal, got_output, expected_output
125 125
126 126
127 127 @skip_without('xxlimited')
128 128 def test_pprint_heap_allocated_type():
129 129 """
130 130 Test that pprint works for heap allocated types.
131 131 """
132 132 import xxlimited
133 133 output = pretty.pretty(xxlimited.Null)
134 134 nt.assert_equal(output, 'xxlimited.Null')
135 135
136 136 def test_pprint_nomod():
137 137 """
138 138 Test that pprint works for classes with no __module__.
139 139 """
140 140 output = pretty.pretty(NoModule)
141 141 nt.assert_equal(output, 'NoModule')
142 142
143 143 def test_pprint_break():
144 144 """
145 145 Test that p.break_ produces expected output
146 146 """
147 147 output = pretty.pretty(Breaking())
148 148 expected = "TG: Breaking(\n ):"
149 149 nt.assert_equal(output, expected)
150 150
151 151 def test_pprint_break_repr():
152 152 """
153 153 Test that p.break_ is used in repr
154 154 """
155 155 output = pretty.pretty(BreakingReprParent())
156 156 expected = "TG: Breaking(\n ):"
157 157 nt.assert_equal(output, expected)
158 158
159 159 def test_bad_repr():
160 160 """Don't raise, even when repr fails"""
161 161 output = pretty.pretty(BadRepr())
162 162 nt.assert_in("failed", output)
163 163 nt.assert_in("at 0x", output)
164 164 nt.assert_in("test_pretty", output)
165 165
166 166 class BadException(Exception):
167 167 def __str__(self):
168 168 return -1
169 169
170 170 class ReallyBadRepr(object):
171 171 __module__ = 1
172 172 @property
173 173 def __class__(self):
174 174 raise ValueError("I am horrible")
175 175
176 176 def __repr__(self):
177 177 raise BadException()
178 178
179 179 def test_really_bad_repr():
180 180 output = pretty.pretty(ReallyBadRepr())
181 181 nt.assert_in("failed", output)
182 182 nt.assert_in("BadException: unknown", output)
183 183 nt.assert_in("unknown type", output)
184 184
185 185
186 186 class SA(object):
187 187 pass
188 188
189 189 class SB(SA):
190 190 pass
191 191
192 192 def test_super_repr():
193 193 output = pretty.pretty(super(SA))
194 194 nt.assert_in("SA", output)
195 195
196 196 sb = SB()
197 197 output = pretty.pretty(super(SA, sb))
198 198 nt.assert_in("SA", output)
199 No newline at end of file
199
200
201 def test_long_list():
202 lis = list(range(10000))
203 p = pretty.pretty(lis)
204 last2 = p.rsplit('\n', 2)[-2:]
205 nt.assert_equal(last2, [' 999,', ' ...]'])
206
207 def test_long_set():
208 s = set(range(10000))
209 p = pretty.pretty(s)
210 last2 = p.rsplit('\n', 2)[-2:]
211 nt.assert_equal(last2, [' 999,', ' ...}'])
212
213 def test_long_tuple():
214 tup = tuple(range(10000))
215 p = pretty.pretty(tup)
216 last2 = p.rsplit('\n', 2)[-2:]
217 nt.assert_equal(last2, [' 999,', ' ...)'])
218
219 def test_long_dict():
220 d = { n:n for n in range(10000) }
221 p = pretty.pretty(d)
222 last2 = p.rsplit('\n', 2)[-2:]
223 nt.assert_equal(last2, [' 999: 999,', ' ...}'])
224
General Comments 0
You need to be logged in to leave comments. Login now