##// END OF EJS Templates
Try and use groups instead
Eric Wieser -
Show More
@@ -1,867 +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_outer_groups(self):
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
209 def _break_outer_groups(self, force=):
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 696 lines = output.splitlines()
691 # insert a leading newline for multi-line objects that are indented
692 if len(lines) > 1 and p.indentation != p.output_width:
693 p.break_()
694 for idx, output_line in enumerate(lines):
695 if idx:
696 p.break_()
697 p.text(output_line)
697 with p.group():
698 for idx, output_line in enumerate(lines):
699 if idx:
700 p.break_()
701 p.text(output_line)
698 702
699 703
700 704 def _function_pprint(obj, p, cycle):
701 705 """Base pprint for all functions and builtin functions."""
702 706 name = _safe_getattr(obj, '__qualname__', obj.__name__)
703 707 mod = obj.__module__
704 708 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
705 709 name = mod + '.' + name
706 710 try:
707 711 func_def = name + str(signature(obj))
708 712 except ValueError:
709 713 func_def = name
710 714 p.text('<function %s>' % func_def)
711 715
712 716
713 717 def _exception_pprint(obj, p, cycle):
714 718 """Base pprint for all exceptions."""
715 719 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
716 720 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
717 721 name = '%s.%s' % (obj.__class__.__module__, name)
718 722 step = len(name) + 1
719 723 p.begin_group(step, name + '(')
720 724 for idx, arg in enumerate(getattr(obj, 'args', ())):
721 725 if idx:
722 726 p.text(',')
723 727 p.breakable()
724 728 p.pretty(arg)
725 729 p.end_group(step, ')')
726 730
727 731
728 732 #: the exception base
729 733 try:
730 734 _exception_base = BaseException
731 735 except NameError:
732 736 _exception_base = Exception
733 737
734 738
735 739 #: printers for builtin types
736 740 _type_pprinters = {
737 741 int: _repr_pprint,
738 742 float: _repr_pprint,
739 743 str: _repr_pprint,
740 744 tuple: _seq_pprinter_factory('(', ')'),
741 745 list: _seq_pprinter_factory('[', ']'),
742 746 dict: _dict_pprinter_factory('{', '}'),
743 747 set: _set_pprinter_factory('{', '}'),
744 748 frozenset: _set_pprinter_factory('frozenset({', '})'),
745 749 super: _super_pprint,
746 750 _re_pattern_type: _re_pattern_pprint,
747 751 type: _type_pprint,
748 752 types.FunctionType: _function_pprint,
749 753 types.BuiltinFunctionType: _function_pprint,
750 754 types.MethodType: _repr_pprint,
751 755 datetime.datetime: _repr_pprint,
752 756 datetime.timedelta: _repr_pprint,
753 757 _exception_base: _exception_pprint
754 758 }
755 759
756 760 # render os.environ like a dict
757 761 _env_type = type(os.environ)
758 762 # future-proof in case os.environ becomes a plain dict?
759 763 if _env_type is not dict:
760 764 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
761 765
762 766 try:
763 767 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
764 768 # using dict.setdefault avoids overwriting the dict printer
765 769 _type_pprinters.setdefault(types.DictProxyType,
766 770 _dict_pprinter_factory('dict_proxy({', '})'))
767 771 _type_pprinters[types.ClassType] = _type_pprint
768 772 _type_pprinters[types.SliceType] = _repr_pprint
769 773 except AttributeError: # Python 3
770 774 _type_pprinters[types.MappingProxyType] = \
771 775 _dict_pprinter_factory('mappingproxy({', '})')
772 776 _type_pprinters[slice] = _repr_pprint
773 777
774 778 try:
775 779 _type_pprinters[long] = _repr_pprint
776 780 _type_pprinters[unicode] = _repr_pprint
777 781 except NameError:
778 782 _type_pprinters[range] = _repr_pprint
779 783 _type_pprinters[bytes] = _repr_pprint
780 784
781 785 #: printers for types specified by name
782 786 _deferred_type_pprinters = {
783 787 }
784 788
785 789 def for_type(typ, func):
786 790 """
787 791 Add a pretty printer for a given type.
788 792 """
789 793 oldfunc = _type_pprinters.get(typ, None)
790 794 if func is not None:
791 795 # To support easy restoration of old pprinters, we need to ignore Nones.
792 796 _type_pprinters[typ] = func
793 797 return oldfunc
794 798
795 799 def for_type_by_name(type_module, type_name, func):
796 800 """
797 801 Add a pretty printer for a type specified by the module and name of a type
798 802 rather than the type object itself.
799 803 """
800 804 key = (type_module, type_name)
801 805 oldfunc = _deferred_type_pprinters.get(key, None)
802 806 if func is not None:
803 807 # To support easy restoration of old pprinters, we need to ignore Nones.
804 808 _deferred_type_pprinters[key] = func
805 809 return oldfunc
806 810
807 811
808 812 #: printers for the default singletons
809 813 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
810 814 NotImplemented]), _repr_pprint)
811 815
812 816
813 817 def _defaultdict_pprint(obj, p, cycle):
814 818 name = obj.__class__.__name__
815 819 with p.group(len(name) + 1, name + '(', ')'):
816 820 if cycle:
817 821 p.text('...')
818 822 else:
819 823 p.pretty(obj.default_factory)
820 824 p.text(',')
821 825 p.breakable()
822 826 p.pretty(dict(obj))
823 827
824 828 def _ordereddict_pprint(obj, p, cycle):
825 829 name = obj.__class__.__name__
826 830 with p.group(len(name) + 1, name + '(', ')'):
827 831 if cycle:
828 832 p.text('...')
829 833 elif len(obj):
830 834 p.pretty(list(obj.items()))
831 835
832 836 def _deque_pprint(obj, p, cycle):
833 837 name = obj.__class__.__name__
834 838 with p.group(len(name) + 1, name + '(', ')'):
835 839 if cycle:
836 840 p.text('...')
837 841 else:
838 842 p.pretty(list(obj))
839 843
840 844
841 845 def _counter_pprint(obj, p, cycle):
842 846 name = obj.__class__.__name__
843 847 with p.group(len(name) + 1, name + '(', ')'):
844 848 if cycle:
845 849 p.text('...')
846 850 elif len(obj):
847 851 p.pretty(dict(obj))
848 852
849 853 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
850 854 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
851 855 for_type_by_name('collections', 'deque', _deque_pprint)
852 856 for_type_by_name('collections', 'Counter', _counter_pprint)
853 857
854 858 if __name__ == '__main__':
855 859 from random import randrange
856 860 class Foo(object):
857 861 def __init__(self):
858 862 self.foo = 1
859 863 self.bar = re.compile(r'\s+')
860 864 self.blub = dict.fromkeys(range(30), randrange(1, 40))
861 865 self.hehe = 23424.234234
862 866 self.list = ["blub", "blah", self]
863 867
864 868 def get_foo(self):
865 869 print("foo")
866 870
867 871 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now