1# -*- coding: utf-8 -*- 2""" 3Python advanced pretty printer. This pretty printer is intended to 4replace the old `pprint` python module which does not allow developers 5to provide their own pretty print callbacks. 6 7This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`. 8 9The following implementations were forked from the IPython project: 10* Copyright (c) 2008-2014, IPython Development Team 11* Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu> 12* Copyright (c) 2001, Janko Hauser <jhauser@zscout.de> 13* Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu> 14 15Example Usage 16------------- 17 18To directly print the representation of an object use `pprint`:: 19 20 from pretty import pretty_print 21 pretty_pprint(complex_object) 22 23To get a string of the output use `pretty`:: 24 25 from pretty import pretty 26 string = pretty(complex_object) 27 28 29Extending 30--------- 31 32The pretty library allows developers to add pretty printing rules for their 33own objects. This process is straightforward. All you have to do is to 34add a `_repr_pretty_` method to your object and call the methods on the 35pretty printer passed:: 36 37 class MyObject(object): 38 39 def _repr_pretty_(self, p, cycle): 40 ... 41 42Here is an example implementation of a `_repr_pretty_` method for a list 43subclass:: 44 45 class MyList(list): 46 47 def _repr_pretty_(self, p, cycle): 48 if cycle: 49 p.text('MyList(...)') 50 else: 51 with p.group(8, 'MyList([', '])'): 52 for idx, item in enumerate(self): 53 if idx: 54 p.text(',') 55 p.breakable() 56 p.pretty(item) 57 58The `cycle` parameter is `True` if pretty detected a cycle. You *have* to 59react to that or the result is an infinite loop. `p.text()` just adds 60non breaking text to the output, `p.breakable()` either adds a whitespace 61or breaks here. If you pass it an argument it's used instead of the 62default space. `p.pretty` prettyprints another object using the pretty print 63method. 64 65The first parameter to the `group` function specifies the extra indentation 66of the next line. In this example the next item will either be on the same 67line (if the items are short enough) or aligned with the right edge of the 68opening bracket of `MyList`. 69 70If you just want to indent something you can use the group function 71without open / close parameters. You can also use this code:: 72 73 with p.indent(2): 74 ... 75 76 77:copyright: 2007 by Armin Ronacher. 78 Portions (c) 2009 by Robert Kern. 79:license: BSD License. 80""" 81import io 82import re 83import sys 84import types 85import datetime 86import contextlib 87import collections 88 89from xonsh.lazyasd import LazyObject, lazyobject 90 91__all__ = [ 92 "pretty", 93 "pretty_print", 94 "PrettyPrinter", 95 "RepresentationPrinter", 96 "for_type", 97 "for_type_by_name", 98] 99 100 101MAX_SEQ_LENGTH = 1000 102 103 104def _safe_getattr(obj, attr, default=None): 105 """Safe version of getattr. 106 107 Same as getattr, but will return ``default`` on any Exception, 108 rather than raising. 109 """ 110 try: 111 return getattr(obj, attr, default) 112 except Exception: 113 return default 114 115 116CUnicodeIO = io.StringIO 117 118 119def pretty( 120 obj, verbose=False, max_width=79, newline="\n", max_seq_length=MAX_SEQ_LENGTH 121): 122 """ 123 Pretty print the object's representation. 124 """ 125 if hasattr(obj, "xonsh_display"): 126 return obj.xonsh_display() 127 128 stream = CUnicodeIO() 129 printer = RepresentationPrinter( 130 stream, verbose, max_width, newline, max_seq_length=max_seq_length 131 ) 132 printer.pretty(obj) 133 printer.flush() 134 return stream.getvalue() 135 136 137def pretty_print( 138 obj, verbose=False, max_width=79, newline="\n", max_seq_length=MAX_SEQ_LENGTH 139): 140 """ 141 Like pretty() but print to stdout. 142 """ 143 printer = RepresentationPrinter( 144 sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length 145 ) 146 printer.pretty(obj) 147 printer.flush() 148 sys.stdout.write(newline) 149 sys.stdout.flush() 150 151 152class _PrettyPrinterBase(object): 153 @contextlib.contextmanager 154 def indent(self, indent): 155 """with statement support for indenting/dedenting.""" 156 self.indentation += indent 157 try: 158 yield 159 finally: 160 self.indentation -= indent 161 162 @contextlib.contextmanager 163 def group(self, indent=0, open="", close=""): 164 """like begin_group / end_group but for the with statement.""" 165 self.begin_group(indent, open) 166 try: 167 yield 168 finally: 169 self.end_group(indent, close) 170 171 172class PrettyPrinter(_PrettyPrinterBase): 173 """ 174 Baseclass for the `RepresentationPrinter` prettyprinter that is used to 175 generate pretty reprs of objects. Contrary to the `RepresentationPrinter` 176 this printer knows nothing about the default pprinters or the `_repr_pretty_` 177 callback method. 178 """ 179 180 def __init__( 181 self, output, max_width=79, newline="\n", max_seq_length=MAX_SEQ_LENGTH 182 ): 183 self.output = output 184 self.max_width = max_width 185 self.newline = newline 186 self.max_seq_length = max_seq_length 187 self.output_width = 0 188 self.buffer_width = 0 189 self.buffer = collections.deque() 190 191 root_group = Group(0) 192 self.group_stack = [root_group] 193 self.group_queue = GroupQueue(root_group) 194 self.indentation = 0 195 196 def _break_outer_groups(self): 197 while self.max_width < self.output_width + self.buffer_width: 198 group = self.group_queue.deq() 199 if not group: 200 return 201 while group.breakables: 202 x = self.buffer.popleft() 203 self.output_width = x.output(self.output, self.output_width) 204 self.buffer_width -= x.width 205 while self.buffer and isinstance(self.buffer[0], Text): 206 x = self.buffer.popleft() 207 self.output_width = x.output(self.output, self.output_width) 208 self.buffer_width -= x.width 209 210 def text(self, obj): 211 """Add literal text to the output.""" 212 width = len(obj) 213 if self.buffer: 214 text = self.buffer[-1] 215 if not isinstance(text, Text): 216 text = Text() 217 self.buffer.append(text) 218 text.add(obj, width) 219 self.buffer_width += width 220 self._break_outer_groups() 221 else: 222 self.output.write(obj) 223 self.output_width += width 224 225 def breakable(self, sep=" "): 226 """ 227 Add a breakable separator to the output. This does not mean that it 228 will automatically break here. If no breaking on this position takes 229 place the `sep` is inserted which default to one space. 230 """ 231 width = len(sep) 232 group = self.group_stack[-1] 233 if group.want_break: 234 self.flush() 235 self.output.write(self.newline) 236 self.output.write(" " * self.indentation) 237 self.output_width = self.indentation 238 self.buffer_width = 0 239 else: 240 self.buffer.append(Breakable(sep, width, self)) 241 self.buffer_width += width 242 self._break_outer_groups() 243 244 def break_(self): 245 """ 246 Explicitly insert a newline into the output, maintaining correct indentation. 247 """ 248 self.flush() 249 self.output.write(self.newline) 250 self.output.write(" " * self.indentation) 251 self.output_width = self.indentation 252 self.buffer_width = 0 253 254 def begin_group(self, indent=0, open=""): 255 """ 256 Begin a group. If you want support for python < 2.5 which doesn't has 257 the with statement this is the preferred way: 258 259 p.begin_group(1, '{') 260 ... 261 p.end_group(1, '}') 262 263 The python 2.5 expression would be this: 264 265 with p.group(1, '{', '}'): 266 ... 267 268 The first parameter specifies the indentation for the next line (usually 269 the width of the opening text), the second the opening text. All 270 parameters are optional. 271 """ 272 if open: 273 self.text(open) 274 group = Group(self.group_stack[-1].depth + 1) 275 self.group_stack.append(group) 276 self.group_queue.enq(group) 277 self.indentation += indent 278 279 def _enumerate(self, seq): 280 """like enumerate, but with an upper limit on the number of items""" 281 for idx, x in enumerate(seq): 282 if self.max_seq_length and idx >= self.max_seq_length: 283 self.text(",") 284 self.breakable() 285 self.text("...") 286 return 287 yield idx, x 288 289 def end_group(self, dedent=0, close=""): 290 """End a group. See `begin_group` for more details.""" 291 self.indentation -= dedent 292 group = self.group_stack.pop() 293 if not group.breakables: 294 self.group_queue.remove(group) 295 if close: 296 self.text(close) 297 298 def flush(self): 299 """Flush data that is left in the buffer.""" 300 for data in self.buffer: 301 self.output_width += data.output(self.output, self.output_width) 302 self.buffer.clear() 303 self.buffer_width = 0 304 305 306def _get_mro(obj_class): 307 """ Get a reasonable method resolution order of a class and its superclasses 308 for both old-style and new-style classes. 309 """ 310 if not hasattr(obj_class, "__mro__"): 311 # Old-style class. Mix in object to make a fake new-style class. 312 try: 313 obj_class = type(obj_class.__name__, (obj_class, object), {}) 314 except TypeError: 315 # Old-style extension type that does not descend from object. 316 # FIXME: try to construct a more thorough MRO. 317 mro = [obj_class] 318 else: 319 mro = obj_class.__mro__[1:-1] 320 else: 321 mro = obj_class.__mro__ 322 return mro 323 324 325class RepresentationPrinter(PrettyPrinter): 326 """ 327 Special pretty printer that has a `pretty` method that calls the pretty 328 printer for a python object. 329 330 This class stores processing data on `self` so you must *never* use 331 this class in a threaded environment. Always lock it or reinstantiate 332 it. 333 334 Instances also have a verbose flag callbacks can access to control their 335 output. For example the default instance repr prints all attributes and 336 methods that are not prefixed by an underscore if the printer is in 337 verbose mode. 338 """ 339 340 def __init__( 341 self, 342 output, 343 verbose=False, 344 max_width=79, 345 newline="\n", 346 singleton_pprinters=None, 347 type_pprinters=None, 348 deferred_pprinters=None, 349 max_seq_length=MAX_SEQ_LENGTH, 350 ): 351 352 PrettyPrinter.__init__( 353 self, output, max_width, newline, max_seq_length=max_seq_length 354 ) 355 self.verbose = verbose 356 self.stack = [] 357 if singleton_pprinters is None: 358 singleton_pprinters = _singleton_pprinters.copy() 359 self.singleton_pprinters = singleton_pprinters 360 if type_pprinters is None: 361 type_pprinters = _type_pprinters.copy() 362 self.type_pprinters = type_pprinters 363 if deferred_pprinters is None: 364 deferred_pprinters = _deferred_type_pprinters.copy() 365 self.deferred_pprinters = deferred_pprinters 366 367 def pretty(self, obj): 368 """Pretty print the given object.""" 369 obj_id = id(obj) 370 cycle = obj_id in self.stack 371 self.stack.append(obj_id) 372 self.begin_group() 373 try: 374 obj_class = _safe_getattr(obj, "__class__", None) or type(obj) 375 # First try to find registered singleton printers for the type. 376 try: 377 printer = self.singleton_pprinters[obj_id] 378 except (TypeError, KeyError): 379 pass 380 else: 381 return printer(obj, self, cycle) 382 # Next walk the mro and check for either: 383 # 1) a registered printer 384 # 2) a _repr_pretty_ method 385 for cls in _get_mro(obj_class): 386 if cls in self.type_pprinters: 387 # printer registered in self.type_pprinters 388 return self.type_pprinters[cls](obj, self, cycle) 389 else: 390 # deferred printer 391 printer = self._in_deferred_types(cls) 392 if printer is not None: 393 return printer(obj, self, cycle) 394 else: 395 # Finally look for special method names. 396 # Some objects automatically create any requested 397 # attribute. Try to ignore most of them by checking for 398 # callability. 399 if "_repr_pretty_" in cls.__dict__: 400 meth = cls._repr_pretty_ 401 if callable(meth): 402 return meth(obj, self, cycle) 403 return _default_pprint(obj, self, cycle) 404 finally: 405 self.end_group() 406 self.stack.pop() 407 408 def _in_deferred_types(self, cls): 409 """ 410 Check if the given class is specified in the deferred type registry. 411 412 Returns the printer from the registry if it exists, and None if the 413 class is not in the registry. Successful matches will be moved to the 414 regular type registry for future use. 415 """ 416 mod = _safe_getattr(cls, "__module__", None) 417 name = _safe_getattr(cls, "__name__", None) 418 key = (mod, name) 419 printer = None 420 if key in self.deferred_pprinters: 421 # Move the printer over to the regular registry. 422 printer = self.deferred_pprinters.pop(key) 423 self.type_pprinters[cls] = printer 424 return printer 425 426 427class Printable(object): 428 def output(self, stream, output_width): 429 return output_width 430 431 432class Text(Printable): 433 def __init__(self): 434 self.objs = [] 435 self.width = 0 436 437 def output(self, stream, output_width): 438 for obj in self.objs: 439 stream.write(obj) 440 return output_width + self.width 441 442 def add(self, obj, width): 443 self.objs.append(obj) 444 self.width += width 445 446 447class Breakable(Printable): 448 def __init__(self, seq, width, pretty): 449 self.obj = seq 450 self.width = width 451 self.pretty = pretty 452 self.indentation = pretty.indentation 453 self.group = pretty.group_stack[-1] 454 self.group.breakables.append(self) 455 456 def output(self, stream, output_width): 457 self.group.breakables.popleft() 458 if self.group.want_break: 459 stream.write(self.pretty.newline) 460 stream.write(" " * self.indentation) 461 return self.indentation 462 if not self.group.breakables: 463 self.pretty.group_queue.remove(self.group) 464 stream.write(self.obj) 465 return output_width + self.width 466 467 468class Group(Printable): 469 def __init__(self, depth): 470 self.depth = depth 471 self.breakables = collections.deque() 472 self.want_break = False 473 474 475class GroupQueue(object): 476 def __init__(self, *groups): 477 self.queue = [] 478 for group in groups: 479 self.enq(group) 480 481 def enq(self, group): 482 depth = group.depth 483 while depth > len(self.queue) - 1: 484 self.queue.append([]) 485 self.queue[depth].append(group) 486 487 def deq(self): 488 for stack in self.queue: 489 for idx, group in enumerate(reversed(stack)): 490 if group.breakables: 491 del stack[idx] 492 group.want_break = True 493 return group 494 for group in stack: 495 group.want_break = True 496 del stack[:] 497 498 def remove(self, group): 499 try: 500 self.queue[group.depth].remove(group) 501 except ValueError: 502 pass 503 504 505@lazyobject 506def _baseclass_reprs(): 507 try: 508 br = (object.__repr__, types.InstanceType.__repr__) 509 except AttributeError: # Python 3 510 br = (object.__repr__,) 511 return br 512 513 514def _default_pprint(obj, p, cycle): 515 """ 516 The default print function. Used if an object does not provide one and 517 it's none of the builtin objects. 518 """ 519 klass = _safe_getattr(obj, "__class__", None) or type(obj) 520 if _safe_getattr(klass, "__repr__", None) not in _baseclass_reprs: 521 # A user-provided repr. Find newlines and replace them with p.break_() 522 _repr_pprint(obj, p, cycle) 523 return 524 p.begin_group(1, "<") 525 p.pretty(klass) 526 p.text(" at 0x%x" % id(obj)) 527 if cycle: 528 p.text(" ...") 529 elif p.verbose: 530 first = True 531 for key in dir(obj): 532 if not key.startswith("_"): 533 try: 534 value = getattr(obj, key) 535 except AttributeError: 536 continue 537 if isinstance(value, types.MethodType): 538 continue 539 if not first: 540 p.text(",") 541 p.breakable() 542 p.text(key) 543 p.text("=") 544 step = len(key) + 1 545 p.indentation += step 546 p.pretty(value) 547 p.indentation -= step 548 first = False 549 p.end_group(1, ">") 550 551 552def _seq_pprinter_factory(start, end, basetype): 553 """ 554 Factory that returns a pprint function useful for sequences. Used by 555 the default pprint for tuples, dicts, and lists. 556 """ 557 558 def inner(obj, p, cycle): 559 typ = type(obj) 560 if ( 561 basetype is not None 562 and typ is not basetype 563 and typ.__repr__ != basetype.__repr__ 564 ): 565 # If the subclass provides its own repr, use it instead. 566 return p.text(typ.__repr__(obj)) 567 568 if cycle: 569 return p.text(start + "..." + end) 570 step = len(start) 571 p.begin_group(step, start) 572 for idx, x in p._enumerate(obj): 573 if idx: 574 p.text(",") 575 p.breakable() 576 p.pretty(x) 577 if len(obj) == 1 and type(obj) is tuple: 578 # Special case for 1-item tuples. 579 p.text(",") 580 p.end_group(step, end) 581 582 return inner 583 584 585def _set_pprinter_factory(start, end, basetype): 586 """ 587 Factory that returns a pprint function useful for sets and frozensets. 588 """ 589 590 def inner(obj, p, cycle): 591 typ = type(obj) 592 if ( 593 basetype is not None 594 and typ is not basetype 595 and typ.__repr__ != basetype.__repr__ 596 ): 597 # If the subclass provides its own repr, use it instead. 598 return p.text(typ.__repr__(obj)) 599 600 if cycle: 601 return p.text(start + "..." + end) 602 if len(obj) == 0: 603 # Special case. 604 p.text(basetype.__name__ + "()") 605 else: 606 step = len(start) 607 p.begin_group(step, start) 608 # Like dictionary keys, we will try to sort the items if there aren't too many 609 items = obj 610 if not (p.max_seq_length and len(obj) >= p.max_seq_length): 611 try: 612 items = sorted(obj) 613 except Exception: 614 # Sometimes the items don't sort. 615 pass 616 for idx, x in p._enumerate(items): 617 if idx: 618 p.text(",") 619 p.breakable() 620 p.pretty(x) 621 p.end_group(step, end) 622 623 return inner 624 625 626def _dict_pprinter_factory(start, end, basetype=None): 627 """ 628 Factory that returns a pprint function used by the default pprint of 629 dicts and dict proxies. 630 """ 631 632 def inner(obj, p, cycle): 633 typ = type(obj) 634 if ( 635 basetype is not None 636 and typ is not basetype 637 and typ.__repr__ != basetype.__repr__ 638 ): 639 # If the subclass provides its own repr, use it instead. 640 return p.text(typ.__repr__(obj)) 641 642 if cycle: 643 return p.text("{...}") 644 p.begin_group(1, start) 645 keys = obj.keys() 646 # if dict isn't large enough to be truncated, sort keys before displaying 647 if not (p.max_seq_length and len(obj) >= p.max_seq_length): 648 try: 649 keys = sorted(keys) 650 except Exception: 651 # Sometimes the keys don't sort. 652 pass 653 for idx, key in p._enumerate(keys): 654 if idx: 655 p.text(",") 656 p.breakable() 657 p.pretty(key) 658 p.text(": ") 659 p.pretty(obj[key]) 660 p.end_group(1, end) 661 662 return inner 663 664 665def _super_pprint(obj, p, cycle): 666 """The pprint for the super type.""" 667 p.begin_group(8, "<super: ") 668 p.pretty(obj.__thisclass__) 669 p.text(",") 670 p.breakable() 671 p.pretty(obj.__self__) 672 p.end_group(8, ">") 673 674 675def _re_pattern_pprint(obj, p, cycle): 676 """The pprint function for regular expression patterns.""" 677 p.text("re.compile(") 678 pattern = repr(obj.pattern) 679 if pattern[:1] in "uU": 680 pattern = pattern[1:] 681 prefix = "ur" 682 else: 683 prefix = "r" 684 pattern = prefix + pattern.replace("\\\\", "\\") 685 p.text(pattern) 686 if obj.flags: 687 p.text(",") 688 p.breakable() 689 done_one = False 690 for flag in ( 691 "TEMPLATE", 692 "IGNORECASE", 693 "LOCALE", 694 "MULTILINE", 695 "DOTALL", 696 "UNICODE", 697 "VERBOSE", 698 "DEBUG", 699 ): 700 if obj.flags & getattr(re, flag): 701 if done_one: 702 p.text("|") 703 p.text("re." + flag) 704 done_one = True 705 p.text(")") 706 707 708def _type_pprint(obj, p, cycle): 709 """The pprint for classes and types.""" 710 # Heap allocated types might not have the module attribute, 711 # and others may set it to None. 712 713 # Checks for a __repr__ override in the metaclass 714 if type(obj).__repr__ is not type.__repr__: 715 _repr_pprint(obj, p, cycle) 716 return 717 718 mod = _safe_getattr(obj, "__module__", None) 719 try: 720 name = obj.__qualname__ 721 if not isinstance(name, str): 722 # This can happen if the type implements __qualname__ as a property 723 # or other descriptor in Python 2. 724 raise Exception("Try __name__") 725 except Exception: 726 name = obj.__name__ 727 if not isinstance(name, str): 728 name = "<unknown type>" 729 730 if mod in (None, "__builtin__", "builtins", "exceptions"): 731 p.text(name) 732 else: 733 p.text(mod + "." + name) 734 735 736def _repr_pprint(obj, p, cycle): 737 """A pprint that just redirects to the normal repr function.""" 738 # Find newlines and replace them with p.break_() 739 output = repr(obj) 740 for idx, output_line in enumerate(output.splitlines()): 741 if idx: 742 p.break_() 743 p.text(output_line) 744 745 746def _function_pprint(obj, p, cycle): 747 """Base pprint for all functions and builtin functions.""" 748 name = _safe_getattr(obj, "__qualname__", obj.__name__) 749 mod = obj.__module__ 750 if mod and mod not in ("__builtin__", "builtins", "exceptions"): 751 name = mod + "." + name 752 p.text("<function %s>" % name) 753 754 755def _exception_pprint(obj, p, cycle): 756 """Base pprint for all exceptions.""" 757 name = getattr(obj.__class__, "__qualname__", obj.__class__.__name__) 758 if obj.__class__.__module__ not in ("exceptions", "builtins"): 759 name = "%s.%s" % (obj.__class__.__module__, name) 760 step = len(name) + 1 761 p.begin_group(step, name + "(") 762 for idx, arg in enumerate(getattr(obj, "args", ())): 763 if idx: 764 p.text(",") 765 p.breakable() 766 p.pretty(arg) 767 p.end_group(step, ")") 768 769 770@lazyobject 771def _type_pprinters(): 772 #: printers for builtin types 773 tp = { 774 int: _repr_pprint, 775 float: _repr_pprint, 776 str: _repr_pprint, 777 tuple: _seq_pprinter_factory("(", ")", tuple), 778 list: _seq_pprinter_factory("[", "]", list), 779 dict: _dict_pprinter_factory("{", "}", dict), 780 set: _set_pprinter_factory("{", "}", set), 781 frozenset: _set_pprinter_factory("frozenset({", "})", frozenset), 782 super: _super_pprint, 783 type(re.compile("")): _re_pattern_pprint, 784 type: _type_pprint, 785 types.FunctionType: _function_pprint, 786 types.BuiltinFunctionType: _function_pprint, 787 types.MethodType: _repr_pprint, 788 datetime.datetime: _repr_pprint, 789 datetime.timedelta: _repr_pprint, 790 } 791 #: the exception base 792 try: 793 _exception_base = BaseException 794 except NameError: 795 _exception_base = Exception 796 tp[_exception_base] = _exception_pprint 797 try: 798 tp[types.DictProxyType] = _dict_pprinter_factory("<dictproxy {", "}>") 799 tp[types.ClassType] = _type_pprint 800 tp[types.SliceType] = _repr_pprint 801 except AttributeError: # Python 3 802 tp[slice] = _repr_pprint 803 try: 804 tp[xrange] = _repr_pprint 805 tp[long] = _repr_pprint 806 tp[unicode] = _repr_pprint 807 except NameError: 808 tp[range] = _repr_pprint 809 tp[bytes] = _repr_pprint 810 return tp 811 812 813#: printers for types specified by name 814@lazyobject 815def _deferred_type_pprinters(): 816 dtp = {} 817 for_type_by_name("collections", "defaultdict", _defaultdict_pprint, dtp=dtp) 818 for_type_by_name("collections", "OrderedDict", _ordereddict_pprint, dtp=dtp) 819 for_type_by_name("collections", "deque", _deque_pprint, dtp=dtp) 820 for_type_by_name("collections", "Counter", _counter_pprint, dtp=dtp) 821 return dtp 822 823 824def for_type(typ, func): 825 """ 826 Add a pretty printer for a given type. 827 """ 828 oldfunc = _type_pprinters.get(typ, None) 829 if func is not None: 830 # To support easy restoration of old pprinters, we need to ignore Nones. 831 _type_pprinters[typ] = func 832 return oldfunc 833 834 835def for_type_by_name(type_module, type_name, func, dtp=None): 836 """ 837 Add a pretty printer for a type specified by the module and name of a type 838 rather than the type object itself. 839 """ 840 if dtp is None: 841 dtp = _deferred_type_pprinters 842 key = (type_module, type_name) 843 oldfunc = dtp.get(key, None) 844 if func is not None: 845 # To support easy restoration of old pprinters, we need to ignore Nones. 846 dtp[key] = func 847 return oldfunc 848 849 850#: printers for the default singletons 851_singleton_pprinters = LazyObject( 852 lambda: dict.fromkeys( 853 map(id, [None, True, False, Ellipsis, NotImplemented]), _repr_pprint 854 ), 855 globals(), 856 "_singleton_pprinters", 857) 858 859 860def _defaultdict_pprint(obj, p, cycle): 861 name = obj.__class__.__name__ 862 with p.group(len(name) + 1, name + "(", ")"): 863 if cycle: 864 p.text("...") 865 else: 866 p.pretty(obj.default_factory) 867 p.text(",") 868 p.breakable() 869 p.pretty(dict(obj)) 870 871 872def _ordereddict_pprint(obj, p, cycle): 873 name = obj.__class__.__name__ 874 with p.group(len(name) + 1, name + "(", ")"): 875 if cycle: 876 p.text("...") 877 elif len(obj): 878 p.pretty(list(obj.items())) 879 880 881def _deque_pprint(obj, p, cycle): 882 name = obj.__class__.__name__ 883 with p.group(len(name) + 1, name + "(", ")"): 884 if cycle: 885 p.text("...") 886 else: 887 p.pretty(list(obj)) 888 889 890def _counter_pprint(obj, p, cycle): 891 name = obj.__class__.__name__ 892 with p.group(len(name) + 1, name + "(", ")"): 893 if cycle: 894 p.text("...") 895 elif len(obj): 896 p.pretty(dict(obj)) 897