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