##// END OF EJS Templates
Miscellaneous Py 3 fixes
Thomas Kluyver -
Show More
@@ -1,790 +1,791 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Python advanced pretty printer. This pretty printer is intended to
4 4 replace the old `pprint` python module which does not allow developers
5 5 to provide their own pretty print callbacks.
6 6
7 7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8 8
9 9
10 10 Example Usage
11 11 -------------
12 12
13 13 To directly print the representation of an object use `pprint`::
14 14
15 15 from pretty import pprint
16 16 pprint(complex_object)
17 17
18 18 To get a string of the output use `pretty`::
19 19
20 20 from pretty import pretty
21 21 string = pretty(complex_object)
22 22
23 23
24 24 Extending
25 25 ---------
26 26
27 27 The pretty library allows developers to add pretty printing rules for their
28 28 own objects. This process is straightforward. All you have to do is to
29 29 add a `_repr_pretty_` method to your object and call the methods on the
30 30 pretty printer passed::
31 31
32 32 class MyObject(object):
33 33
34 34 def _repr_pretty_(self, p, cycle):
35 35 ...
36 36
37 37 Depending on the python version you want to support you have two
38 38 possibilities. The following list shows the python 2.5 version and the
39 39 compatibility one.
40 40
41 41
42 42 Here the example implementation of a `_repr_pretty_` method for a list
43 43 subclass for python 2.5 and higher (python 2.5 requires the with statement
44 44 __future__ import)::
45 45
46 46 class MyList(list):
47 47
48 48 def _repr_pretty_(self, p, cycle):
49 49 if cycle:
50 50 p.text('MyList(...)')
51 51 else:
52 52 with p.group(8, 'MyList([', '])'):
53 53 for idx, item in enumerate(self):
54 54 if idx:
55 55 p.text(',')
56 56 p.breakable()
57 57 p.pretty(item)
58 58
59 59 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
60 60 react to that or the result is an infinite loop. `p.text()` just adds
61 61 non breaking text to the output, `p.breakable()` either adds a whitespace
62 62 or breaks here. If you pass it an argument it's used instead of the
63 63 default space. `p.pretty` prettyprints another object using the pretty print
64 64 method.
65 65
66 66 The first parameter to the `group` function specifies the extra indentation
67 67 of the next line. In this example the next item will either be not
68 68 breaked (if the items are short enough) or aligned with the right edge of
69 69 the opening bracked of `MyList`.
70 70
71 71 If you want to support python 2.4 and lower you can use this code::
72 72
73 73 class MyList(list):
74 74
75 75 def _repr_pretty_(self, p, cycle):
76 76 if cycle:
77 77 p.text('MyList(...)')
78 78 else:
79 79 p.begin_group(8, 'MyList([')
80 80 for idx, item in enumerate(self):
81 81 if idx:
82 82 p.text(',')
83 83 p.breakable()
84 84 p.pretty(item)
85 85 p.end_group(8, '])')
86 86
87 87 If you just want to indent something you can use the group function
88 88 without open / close parameters. Under python 2.5 you can also use this
89 89 code::
90 90
91 91 with p.indent(2):
92 92 ...
93 93
94 94 Or under python2.4 you might want to modify ``p.indentation`` by hand but
95 95 this is rather ugly.
96 96
97 97 Inheritance diagram:
98 98
99 99 .. inheritance-diagram:: IPython.lib.pretty
100 100 :parts: 3
101 101
102 102 :copyright: 2007 by Armin Ronacher.
103 103 Portions (c) 2009 by Robert Kern.
104 104 :license: BSD License.
105 105 """
106 106 from __future__ import print_function
107 107 from contextlib import contextmanager
108 108 import sys
109 109 import types
110 110 import re
111 111 import datetime
112 112 from io import StringIO
113 113 from collections import deque
114 114
115 115
116 116 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
117 117 'for_type', 'for_type_by_name']
118 118
119 119
120 120 _re_pattern_type = type(re.compile(''))
121 121
122 122
123 123 def pretty(obj, verbose=False, max_width=79, newline='\n'):
124 124 """
125 125 Pretty print the object's representation.
126 126 """
127 127 stream = StringIO()
128 128 printer = RepresentationPrinter(stream, verbose, max_width, newline)
129 129 printer.pretty(obj)
130 130 printer.flush()
131 131 return stream.getvalue()
132 132
133 133
134 134 def pprint(obj, verbose=False, max_width=79, newline='\n'):
135 135 """
136 136 Like `pretty` but print to stdout.
137 137 """
138 138 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline)
139 139 printer.pretty(obj)
140 140 printer.flush()
141 141 sys.stdout.write(newline)
142 142 sys.stdout.flush()
143 143
144 144 class _PrettyPrinterBase(object):
145 145
146 146 @contextmanager
147 147 def indent(self, indent):
148 148 """with statement support for indenting/dedenting."""
149 149 self.indentation += indent
150 150 try:
151 151 yield
152 152 finally:
153 153 self.indentation -= indent
154 154
155 155 @contextmanager
156 156 def group(self, indent=0, open='', close=''):
157 157 """like begin_group / end_group but for the with statement."""
158 158 self.begin_group(indent, open)
159 159 try:
160 160 yield
161 161 finally:
162 162 self.end_group(indent, close)
163 163
164 164 class PrettyPrinter(_PrettyPrinterBase):
165 165 """
166 166 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
167 167 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
168 168 this printer knows nothing about the default pprinters or the `_repr_pretty_`
169 169 callback method.
170 170 """
171 171
172 172 def __init__(self, output, max_width=79, newline='\n'):
173 173 self.output = output
174 174 self.max_width = max_width
175 175 self.newline = newline
176 176 self.output_width = 0
177 177 self.buffer_width = 0
178 178 self.buffer = deque()
179 179
180 180 root_group = Group(0)
181 181 self.group_stack = [root_group]
182 182 self.group_queue = GroupQueue(root_group)
183 183 self.indentation = 0
184 184
185 185 def _break_outer_groups(self):
186 186 while self.max_width < self.output_width + self.buffer_width:
187 187 group = self.group_queue.deq()
188 188 if not group:
189 189 return
190 190 while group.breakables:
191 191 x = self.buffer.popleft()
192 192 self.output_width = x.output(self.output, self.output_width)
193 193 self.buffer_width -= x.width
194 194 while self.buffer and isinstance(self.buffer[0], Text):
195 195 x = self.buffer.popleft()
196 196 self.output_width = x.output(self.output, self.output_width)
197 197 self.buffer_width -= x.width
198 198
199 199 def text(self, obj):
200 200 """Add literal text to the output."""
201 201 width = len(obj)
202 202 if self.buffer:
203 203 text = self.buffer[-1]
204 204 if not isinstance(text, Text):
205 205 text = Text()
206 206 self.buffer.append(text)
207 207 text.add(obj, width)
208 208 self.buffer_width += width
209 209 self._break_outer_groups()
210 210 else:
211 211 self.output.write(obj)
212 212 self.output_width += width
213 213
214 214 def breakable(self, sep=' '):
215 215 """
216 216 Add a breakable separator to the output. This does not mean that it
217 217 will automatically break here. If no breaking on this position takes
218 218 place the `sep` is inserted which default to one space.
219 219 """
220 220 width = len(sep)
221 221 group = self.group_stack[-1]
222 222 if group.want_break:
223 223 self.flush()
224 224 self.output.write(self.newline)
225 225 self.output.write(' ' * self.indentation)
226 226 self.output_width = self.indentation
227 227 self.buffer_width = 0
228 228 else:
229 229 self.buffer.append(Breakable(sep, width, self))
230 230 self.buffer_width += width
231 231 self._break_outer_groups()
232 232
233 233 def break_(self):
234 234 """
235 235 Explicitly insert a newline into the output, maintaining correct indentation.
236 236 """
237 237 self.flush()
238 238 self.output.write(self.newline)
239 239 self.output.write(' ' * self.indentation)
240 240 self.output_width = self.indentation
241 241 self.buffer_width = 0
242 242
243 243
244 244 def begin_group(self, indent=0, open=''):
245 245 """
246 246 Begin a group. If you want support for python < 2.5 which doesn't has
247 247 the with statement this is the preferred way:
248 248
249 249 p.begin_group(1, '{')
250 250 ...
251 251 p.end_group(1, '}')
252 252
253 253 The python 2.5 expression would be this:
254 254
255 255 with p.group(1, '{', '}'):
256 256 ...
257 257
258 258 The first parameter specifies the indentation for the next line (usually
259 259 the width of the opening text), the second the opening text. All
260 260 parameters are optional.
261 261 """
262 262 if open:
263 263 self.text(open)
264 264 group = Group(self.group_stack[-1].depth + 1)
265 265 self.group_stack.append(group)
266 266 self.group_queue.enq(group)
267 267 self.indentation += indent
268 268
269 269 def end_group(self, dedent=0, close=''):
270 270 """End a group. See `begin_group` for more details."""
271 271 self.indentation -= dedent
272 272 group = self.group_stack.pop()
273 273 if not group.breakables:
274 274 self.group_queue.remove(group)
275 275 if close:
276 276 self.text(close)
277 277
278 278 def flush(self):
279 279 """Flush data that is left in the buffer."""
280 280 for data in self.buffer:
281 281 self.output_width += data.output(self.output, self.output_width)
282 282 self.buffer.clear()
283 283 self.buffer_width = 0
284 284
285 285
286 286 def _get_mro(obj_class):
287 287 """ Get a reasonable method resolution order of a class and its superclasses
288 288 for both old-style and new-style classes.
289 289 """
290 290 if not hasattr(obj_class, '__mro__'):
291 291 # Old-style class. Mix in object to make a fake new-style class.
292 292 try:
293 293 obj_class = type(obj_class.__name__, (obj_class, object), {})
294 294 except TypeError:
295 295 # Old-style extension type that does not descend from object.
296 296 # FIXME: try to construct a more thorough MRO.
297 297 mro = [obj_class]
298 298 else:
299 299 mro = obj_class.__mro__[1:-1]
300 300 else:
301 301 mro = obj_class.__mro__
302 302 return mro
303 303
304 304
305 305 class RepresentationPrinter(PrettyPrinter):
306 306 """
307 307 Special pretty printer that has a `pretty` method that calls the pretty
308 308 printer for a python object.
309 309
310 310 This class stores processing data on `self` so you must *never* use
311 311 this class in a threaded environment. Always lock it or reinstanciate
312 312 it.
313 313
314 314 Instances also have a verbose flag callbacks can access to control their
315 315 output. For example the default instance repr prints all attributes and
316 316 methods that are not prefixed by an underscore if the printer is in
317 317 verbose mode.
318 318 """
319 319
320 320 def __init__(self, output, verbose=False, max_width=79, newline='\n',
321 321 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None):
322 322
323 323 PrettyPrinter.__init__(self, output, max_width, newline)
324 324 self.verbose = verbose
325 325 self.stack = []
326 326 if singleton_pprinters is None:
327 327 singleton_pprinters = _singleton_pprinters.copy()
328 328 self.singleton_pprinters = singleton_pprinters
329 329 if type_pprinters is None:
330 330 type_pprinters = _type_pprinters.copy()
331 331 self.type_pprinters = type_pprinters
332 332 if deferred_pprinters is None:
333 333 deferred_pprinters = _deferred_type_pprinters.copy()
334 334 self.deferred_pprinters = deferred_pprinters
335 335
336 336 def pretty(self, obj):
337 337 """Pretty print the given object."""
338 338 obj_id = id(obj)
339 339 cycle = obj_id in self.stack
340 340 self.stack.append(obj_id)
341 341 self.begin_group()
342 342 try:
343 343 obj_class = getattr(obj, '__class__', None) or type(obj)
344 344 # First try to find registered singleton printers for the type.
345 345 try:
346 346 printer = self.singleton_pprinters[obj_id]
347 347 except (TypeError, KeyError):
348 348 pass
349 349 else:
350 350 return printer(obj, self, cycle)
351 351 # Next walk the mro and check for either:
352 352 # 1) a registered printer
353 353 # 2) a _repr_pretty_ method
354 354 for cls in _get_mro(obj_class):
355 355 if cls in self.type_pprinters:
356 356 # printer registered in self.type_pprinters
357 357 return self.type_pprinters[cls](obj, self, cycle)
358 358 else:
359 359 # deferred printer
360 360 printer = self._in_deferred_types(cls)
361 361 if printer is not None:
362 362 return printer(obj, self, cycle)
363 363 else:
364 364 # Finally look for special method names.
365 365 # Some objects automatically create any requested
366 366 # attribute. Try to ignore most of them by checking for
367 367 # callability.
368 368 if '_repr_pretty_' in cls.__dict__:
369 369 meth = cls._repr_pretty_
370 370 if callable(meth):
371 371 return meth(obj, self, cycle)
372 372 return _default_pprint(obj, self, cycle)
373 373 finally:
374 374 self.end_group()
375 375 self.stack.pop()
376 376
377 377 def _in_deferred_types(self, cls):
378 378 """
379 379 Check if the given class is specified in the deferred type registry.
380 380
381 381 Returns the printer from the registry if it exists, and None if the
382 382 class is not in the registry. Successful matches will be moved to the
383 383 regular type registry for future use.
384 384 """
385 385 mod = getattr(cls, '__module__', None)
386 386 name = getattr(cls, '__name__', None)
387 387 key = (mod, name)
388 388 printer = None
389 389 if key in self.deferred_pprinters:
390 390 # Move the printer over to the regular registry.
391 391 printer = self.deferred_pprinters.pop(key)
392 392 self.type_pprinters[cls] = printer
393 393 return printer
394 394
395 395
396 396 class Printable(object):
397 397
398 398 def output(self, stream, output_width):
399 399 return output_width
400 400
401 401
402 402 class Text(Printable):
403 403
404 404 def __init__(self):
405 405 self.objs = []
406 406 self.width = 0
407 407
408 408 def output(self, stream, output_width):
409 409 for obj in self.objs:
410 410 stream.write(obj)
411 411 return output_width + self.width
412 412
413 413 def add(self, obj, width):
414 414 self.objs.append(obj)
415 415 self.width += width
416 416
417 417
418 418 class Breakable(Printable):
419 419
420 420 def __init__(self, seq, width, pretty):
421 421 self.obj = seq
422 422 self.width = width
423 423 self.pretty = pretty
424 424 self.indentation = pretty.indentation
425 425 self.group = pretty.group_stack[-1]
426 426 self.group.breakables.append(self)
427 427
428 428 def output(self, stream, output_width):
429 429 self.group.breakables.popleft()
430 430 if self.group.want_break:
431 431 stream.write(self.pretty.newline)
432 432 stream.write(' ' * self.indentation)
433 433 return self.indentation
434 434 if not self.group.breakables:
435 435 self.pretty.group_queue.remove(self.group)
436 436 stream.write(self.obj)
437 437 return output_width + self.width
438 438
439 439
440 440 class Group(Printable):
441 441
442 442 def __init__(self, depth):
443 443 self.depth = depth
444 444 self.breakables = deque()
445 445 self.want_break = False
446 446
447 447
448 448 class GroupQueue(object):
449 449
450 450 def __init__(self, *groups):
451 451 self.queue = []
452 452 for group in groups:
453 453 self.enq(group)
454 454
455 455 def enq(self, group):
456 456 depth = group.depth
457 457 while depth > len(self.queue) - 1:
458 458 self.queue.append([])
459 459 self.queue[depth].append(group)
460 460
461 461 def deq(self):
462 462 for stack in self.queue:
463 463 for idx, group in enumerate(reversed(stack)):
464 464 if group.breakables:
465 465 del stack[idx]
466 466 group.want_break = True
467 467 return group
468 468 for group in stack:
469 469 group.want_break = True
470 470 del stack[:]
471 471
472 472 def remove(self, group):
473 473 try:
474 474 self.queue[group.depth].remove(group)
475 475 except ValueError:
476 476 pass
477 477
478 478 try:
479 479 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
480 480 except AttributeError: # Python 3
481 481 _baseclass_reprs = (object.__repr__,)
482 482
483 483
484 484 def _default_pprint(obj, p, cycle):
485 485 """
486 486 The default print function. Used if an object does not provide one and
487 487 it's none of the builtin objects.
488 488 """
489 489 klass = getattr(obj, '__class__', None) or type(obj)
490 490 if getattr(klass, '__repr__', None) not in _baseclass_reprs:
491 491 # A user-provided repr. Find newlines and replace them with p.break_()
492 492 output = repr(obj)
493 493 for idx,output_line in enumerate(output.splitlines()):
494 494 if idx:
495 495 p.break_()
496 496 p.text(output_line)
497 497 return
498 498 p.begin_group(1, '<')
499 499 p.pretty(klass)
500 500 p.text(' at 0x%x' % id(obj))
501 501 if cycle:
502 502 p.text(' ...')
503 503 elif p.verbose:
504 504 first = True
505 505 for key in dir(obj):
506 506 if not key.startswith('_'):
507 507 try:
508 508 value = getattr(obj, key)
509 509 except AttributeError:
510 510 continue
511 511 if isinstance(value, types.MethodType):
512 512 continue
513 513 if not first:
514 514 p.text(',')
515 515 p.breakable()
516 516 p.text(key)
517 517 p.text('=')
518 518 step = len(key) + 1
519 519 p.indentation += step
520 520 p.pretty(value)
521 521 p.indentation -= step
522 522 first = False
523 523 p.end_group(1, '>')
524 524
525 525
526 526 def _seq_pprinter_factory(start, end, basetype):
527 527 """
528 528 Factory that returns a pprint function useful for sequences. Used by
529 529 the default pprint for tuples, dicts, and lists.
530 530 """
531 531 def inner(obj, p, cycle):
532 532 typ = type(obj)
533 533 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
534 534 # If the subclass provides its own repr, use it instead.
535 535 return p.text(typ.__repr__(obj))
536 536
537 537 if cycle:
538 538 return p.text(start + '...' + end)
539 539 step = len(start)
540 540 p.begin_group(step, start)
541 541 for idx, x in enumerate(obj):
542 542 if idx:
543 543 p.text(',')
544 544 p.breakable()
545 545 p.pretty(x)
546 546 if len(obj) == 1 and type(obj) is tuple:
547 547 # Special case for 1-item tuples.
548 548 p.text(',')
549 549 p.end_group(step, end)
550 550 return inner
551 551
552 552
553 553 def _set_pprinter_factory(start, end, basetype):
554 554 """
555 555 Factory that returns a pprint function useful for sets and frozensets.
556 556 """
557 557 def inner(obj, p, cycle):
558 558 typ = type(obj)
559 559 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
560 560 # If the subclass provides its own repr, use it instead.
561 561 return p.text(typ.__repr__(obj))
562 562
563 563 if cycle:
564 564 return p.text(start + '...' + end)
565 565 if len(obj) == 0:
566 566 # Special case.
567 567 p.text(basetype.__name__ + '()')
568 568 else:
569 569 step = len(start)
570 570 p.begin_group(step, start)
571 571 # Like dictionary keys, we will try to sort the items.
572 572 items = list(obj)
573 573 try:
574 574 items.sort()
575 575 except Exception:
576 576 # Sometimes the items don't sort.
577 577 pass
578 578 for idx, x in enumerate(items):
579 579 if idx:
580 580 p.text(',')
581 581 p.breakable()
582 582 p.pretty(x)
583 583 p.end_group(step, end)
584 584 return inner
585 585
586 586
587 587 def _dict_pprinter_factory(start, end, basetype=None):
588 588 """
589 589 Factory that returns a pprint function used by the default pprint of
590 590 dicts and dict proxies.
591 591 """
592 592 def inner(obj, p, cycle):
593 593 typ = type(obj)
594 594 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
595 595 # If the subclass provides its own repr, use it instead.
596 596 return p.text(typ.__repr__(obj))
597 597
598 598 if cycle:
599 599 return p.text('{...}')
600 600 p.begin_group(1, start)
601 601 keys = obj.keys()
602 602 try:
603 603 keys.sort()
604 604 except Exception as e:
605 605 # Sometimes the keys don't sort.
606 606 pass
607 607 for idx, key in enumerate(keys):
608 608 if idx:
609 609 p.text(',')
610 610 p.breakable()
611 611 p.pretty(key)
612 612 p.text(': ')
613 613 p.pretty(obj[key])
614 614 p.end_group(1, end)
615 615 return inner
616 616
617 617
618 618 def _super_pprint(obj, p, cycle):
619 619 """The pprint for the super type."""
620 620 p.begin_group(8, '<super: ')
621 621 p.pretty(obj.__self_class__)
622 622 p.text(',')
623 623 p.breakable()
624 624 p.pretty(obj.__self__)
625 625 p.end_group(8, '>')
626 626
627 627
628 628 def _re_pattern_pprint(obj, p, cycle):
629 629 """The pprint function for regular expression patterns."""
630 630 p.text('re.compile(')
631 631 pattern = repr(obj.pattern)
632 632 if pattern[:1] in 'uU':
633 633 pattern = pattern[1:]
634 634 prefix = 'ur'
635 635 else:
636 636 prefix = 'r'
637 637 pattern = prefix + pattern.replace('\\\\', '\\')
638 638 p.text(pattern)
639 639 if obj.flags:
640 640 p.text(',')
641 641 p.breakable()
642 642 done_one = False
643 643 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
644 644 'UNICODE', 'VERBOSE', 'DEBUG'):
645 645 if obj.flags & getattr(re, flag):
646 646 if done_one:
647 647 p.text('|')
648 648 p.text('re.' + flag)
649 649 done_one = True
650 650 p.text(')')
651 651
652 652
653 653 def _type_pprint(obj, p, cycle):
654 654 """The pprint for classes and types."""
655 655 mod = getattr(obj, '__module__', None)
656 656 if mod is None:
657 657 # Heap allocated types might not have the module attribute,
658 658 # and others may set it to None.
659 659 return p.text(obj.__name__)
660 660
661 661 if mod in ('__builtin__', 'builtins', 'exceptions'):
662 662 name = obj.__name__
663 663 else:
664 664 name = mod + '.' + obj.__name__
665 665 p.text(name)
666 666
667 667
668 668 def _repr_pprint(obj, p, cycle):
669 669 """A pprint that just redirects to the normal repr function."""
670 670 p.text(repr(obj))
671 671
672 672
673 673 def _function_pprint(obj, p, cycle):
674 674 """Base pprint for all functions and builtin functions."""
675 675 if obj.__module__ in ('__builtin__', 'builtins', 'exceptions') or not obj.__module__:
676 676 name = obj.__name__
677 677 else:
678 678 name = obj.__module__ + '.' + obj.__name__
679 679 p.text('<function %s>' % name)
680 680
681 681
682 682 def _exception_pprint(obj, p, cycle):
683 683 """Base pprint for all exceptions."""
684 684 if obj.__class__.__module__ in ('exceptions', 'builtins'):
685 685 name = obj.__class__.__name__
686 686 else:
687 687 name = '%s.%s' % (
688 688 obj.__class__.__module__,
689 689 obj.__class__.__name__
690 690 )
691 691 step = len(name) + 1
692 692 p.begin_group(step, name + '(')
693 693 for idx, arg in enumerate(getattr(obj, 'args', ())):
694 694 if idx:
695 695 p.text(',')
696 696 p.breakable()
697 697 p.pretty(arg)
698 698 p.end_group(step, ')')
699 699
700 700
701 701 #: the exception base
702 702 try:
703 703 _exception_base = BaseException
704 704 except NameError:
705 705 _exception_base = Exception
706 706
707 707
708 708 #: printers for builtin types
709 709 _type_pprinters = {
710 710 int: _repr_pprint,
711 711 float: _repr_pprint,
712 712 str: _repr_pprint,
713 713 tuple: _seq_pprinter_factory('(', ')', tuple),
714 714 list: _seq_pprinter_factory('[', ']', list),
715 715 dict: _dict_pprinter_factory('{', '}', dict),
716 716
717 717 set: _set_pprinter_factory('{', '}', set),
718 718 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
719 719 super: _super_pprint,
720 720 _re_pattern_type: _re_pattern_pprint,
721 721 type: _type_pprint,
722 722 types.FunctionType: _function_pprint,
723 723 types.BuiltinFunctionType: _function_pprint,
724 types.SliceType: _repr_pprint,
725 724 types.MethodType: _repr_pprint,
726 725
727 726 datetime.datetime: _repr_pprint,
728 727 datetime.timedelta: _repr_pprint,
729 728 _exception_base: _exception_pprint
730 729 }
731 730
732 731 try:
733 732 _type_pprinters[types.DictProxyType] = _dict_pprinter_factory('<dictproxy {', '}>')
734 733 _type_pprinters[types.ClassType] = _type_pprint
735 _type_pprinters[long] = _repr_pprint
736 _type_pprinters[unicode] = _repr_pprint
737 except (AttributeError, NameError): # Python 3
738 _type_pprinters[bytes] = _repr_pprint
734 _type_pprinters[types.SliceType] = _repr_pprint
735 except AttributeError: # Python 3
736 _type_pprinters[slice] = _repr_pprint
739 737
740 738 try:
741 739 _type_pprinters[xrange] = _repr_pprint
740 _type_pprinters[long] = _repr_pprint
741 _type_pprinters[unicode] = _repr_pprint
742 742 except NameError:
743 743 _type_pprinters[range] = _repr_pprint
744 _type_pprinters[bytes] = _repr_pprint
744 745
745 746 #: printers for types specified by name
746 747 _deferred_type_pprinters = {
747 748 }
748 749
749 750 def for_type(typ, func):
750 751 """
751 752 Add a pretty printer for a given type.
752 753 """
753 754 oldfunc = _type_pprinters.get(typ, None)
754 755 if func is not None:
755 756 # To support easy restoration of old pprinters, we need to ignore Nones.
756 757 _type_pprinters[typ] = func
757 758 return oldfunc
758 759
759 760 def for_type_by_name(type_module, type_name, func):
760 761 """
761 762 Add a pretty printer for a type specified by the module and name of a type
762 763 rather than the type object itself.
763 764 """
764 765 key = (type_module, type_name)
765 766 oldfunc = _deferred_type_pprinters.get(key, None)
766 767 if func is not None:
767 768 # To support easy restoration of old pprinters, we need to ignore Nones.
768 769 _deferred_type_pprinters[key] = func
769 770 return oldfunc
770 771
771 772
772 773 #: printers for the default singletons
773 774 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
774 775 NotImplemented]), _repr_pprint)
775 776
776 777
777 778 if __name__ == '__main__':
778 779 from random import randrange
779 780 class Foo(object):
780 781 def __init__(self):
781 782 self.foo = 1
782 783 self.bar = re.compile(r'\s+')
783 784 self.blub = dict.fromkeys(range(30), randrange(1, 40))
784 785 self.hehe = 23424.234234
785 786 self.list = ["blub", "blah", self]
786 787
787 788 def get_foo(self):
788 789 print("foo")
789 790
790 791 pprint(Foo(), verbose=True)
@@ -1,186 +1,186 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for coloring text in ANSI terminals.
3 3 """
4 4
5 5 #*****************************************************************************
6 6 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
7 7 #
8 8 # Distributed under the terms of the BSD License. The full license is in
9 9 # the file COPYING, distributed as part of this software.
10 10 #*****************************************************************************
11 11
12 12 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
13 13
14 14 import os
15 15
16 16 from IPython.utils.ipstruct import Struct
17 17
18 18 color_templates = (
19 19 # Dark colors
20 20 ("Black" , "0;30"),
21 21 ("Red" , "0;31"),
22 22 ("Green" , "0;32"),
23 23 ("Brown" , "0;33"),
24 24 ("Blue" , "0;34"),
25 25 ("Purple" , "0;35"),
26 26 ("Cyan" , "0;36"),
27 27 ("LightGray" , "0;37"),
28 28 # Light colors
29 29 ("DarkGray" , "1;30"),
30 30 ("LightRed" , "1;31"),
31 31 ("LightGreen" , "1;32"),
32 32 ("Yellow" , "1;33"),
33 33 ("LightBlue" , "1;34"),
34 34 ("LightPurple" , "1;35"),
35 35 ("LightCyan" , "1;36"),
36 36 ("White" , "1;37"),
37 37 # Blinking colors. Probably should not be used in anything serious.
38 38 ("BlinkBlack" , "5;30"),
39 39 ("BlinkRed" , "5;31"),
40 40 ("BlinkGreen" , "5;32"),
41 41 ("BlinkYellow" , "5;33"),
42 42 ("BlinkBlue" , "5;34"),
43 43 ("BlinkPurple" , "5;35"),
44 44 ("BlinkCyan" , "5;36"),
45 45 ("BlinkLightGray", "5;37"),
46 46 )
47 47
48 48 def make_color_table(in_class):
49 49 """Build a set of color attributes in a class.
50 50
51 51 Helper function for building the *TermColors classes."""
52 52
53 53 for name,value in color_templates:
54 54 setattr(in_class,name,in_class._base % value)
55 55
56 56 class TermColors:
57 57 """Color escape sequences.
58 58
59 59 This class defines the escape sequences for all the standard (ANSI?)
60 60 colors in terminals. Also defines a NoColor escape which is just the null
61 61 string, suitable for defining 'dummy' color schemes in terminals which get
62 62 confused by color escapes.
63 63
64 64 This class should be used as a mixin for building color schemes."""
65 65
66 66 NoColor = '' # for color schemes in color-less terminals.
67 67 Normal = '\033[0m' # Reset normal coloring
68 68 _base = '\033[%sm' # Template for all other colors
69 69
70 70 # Build the actual color table as a set of class attributes:
71 71 make_color_table(TermColors)
72 72
73 73 class InputTermColors:
74 74 """Color escape sequences for input prompts.
75 75
76 76 This class is similar to TermColors, but the escapes are wrapped in \001
77 77 and \002 so that readline can properly know the length of each line and
78 78 can wrap lines accordingly. Use this class for any colored text which
79 79 needs to be used in input prompts, such as in calls to raw_input().
80 80
81 81 This class defines the escape sequences for all the standard (ANSI?)
82 82 colors in terminals. Also defines a NoColor escape which is just the null
83 83 string, suitable for defining 'dummy' color schemes in terminals which get
84 84 confused by color escapes.
85 85
86 86 This class should be used as a mixin for building color schemes."""
87 87
88 88 NoColor = '' # for color schemes in color-less terminals.
89 89
90 90 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
91 91 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
92 92 Normal = '\033[0m' # Reset normal coloring
93 93 _base = '\033[%sm' # Template for all other colors
94 94 else:
95 95 Normal = '\001\033[0m\002' # Reset normal coloring
96 96 _base = '\001\033[%sm\002' # Template for all other colors
97 97
98 98 # Build the actual color table as a set of class attributes:
99 99 make_color_table(InputTermColors)
100 100
101 101 class NoColors:
102 102 """This defines all the same names as the colour classes, but maps them to
103 103 empty strings, so it can easily be substituted to turn off colours."""
104 104 NoColor = ''
105 105 Normal = ''
106 106
107 107 for name, value in color_templates:
108 108 setattr(NoColors, name, '')
109 109
110 110 class ColorScheme:
111 111 """Generic color scheme class. Just a name and a Struct."""
112 112 def __init__(self,__scheme_name_,colordict=None,**colormap):
113 113 self.name = __scheme_name_
114 114 if colordict is None:
115 115 self.colors = Struct(**colormap)
116 116 else:
117 117 self.colors = Struct(colordict)
118 118
119 119 def copy(self,name=None):
120 120 """Return a full copy of the object, optionally renaming it."""
121 121 if name is None:
122 122 name = self.name
123 123 return ColorScheme(name, self.colors.dict())
124 124
125 125 class ColorSchemeTable(dict):
126 126 """General class to handle tables of color schemes.
127 127
128 128 It's basically a dict of color schemes with a couple of shorthand
129 129 attributes and some convenient methods.
130 130
131 131 active_scheme_name -> obvious
132 132 active_colors -> actual color table of the active scheme"""
133 133
134 134 def __init__(self,scheme_list=None,default_scheme=''):
135 135 """Create a table of color schemes.
136 136
137 137 The table can be created empty and manually filled or it can be
138 138 created with a list of valid color schemes AND the specification for
139 139 the default active scheme.
140 140 """
141 141
142 142 # create object attributes to be set later
143 143 self.active_scheme_name = ''
144 144 self.active_colors = None
145 145
146 146 if scheme_list:
147 147 if default_scheme == '':
148 148 raise ValueError('you must specify the default color scheme')
149 149 for scheme in scheme_list:
150 150 self.add_scheme(scheme)
151 151 self.set_active_scheme(default_scheme)
152 152
153 153 def copy(self):
154 154 """Return full copy of object"""
155 155 return ColorSchemeTable(self.values(),self.active_scheme_name)
156 156
157 157 def add_scheme(self,new_scheme):
158 158 """Add a new color scheme to the table."""
159 159 if not isinstance(new_scheme,ColorScheme):
160 160 raise ValueError('ColorSchemeTable only accepts ColorScheme instances')
161 161 self[new_scheme.name] = new_scheme
162 162
163 163 def set_active_scheme(self,scheme,case_sensitive=0):
164 164 """Set the currently active scheme.
165 165
166 166 Names are by default compared in a case-insensitive way, but this can
167 167 be changed by setting the parameter case_sensitive to true."""
168 168
169 scheme_names = self.keys()
169 scheme_names = list(self.keys())
170 170 if case_sensitive:
171 171 valid_schemes = scheme_names
172 172 scheme_test = scheme
173 173 else:
174 174 valid_schemes = [s.lower() for s in scheme_names]
175 175 scheme_test = scheme.lower()
176 176 try:
177 177 scheme_idx = valid_schemes.index(scheme_test)
178 178 except ValueError:
179 179 raise ValueError('Unrecognized color scheme: ' + scheme + \
180 180 '\nValid schemes: '+str(scheme_names).replace("'', ",''))
181 181 else:
182 182 active = scheme_names[scheme_idx]
183 183 self.active_scheme_name = active
184 184 self.active_colors = self[active].colors
185 185 # Now allow using '' as an index for the current active scheme
186 186 self[''] = self[active]
General Comments 0
You need to be logged in to leave comments. Login now