10
10
import os .path
11
11
import re
12
12
import sys
13
+ import textwrap
13
14
import threading
14
15
import decimal
15
16
from collections import deque
17
+ from pprint import PrettyPrinter
16
18
17
19
import pytz
18
20
from decorator import decorator
@@ -492,7 +494,7 @@ def _memoize(*all_args, **kwargs):
492
494
return decorator (_memoize )
493
495
494
496
495
- def _list_repr_elided (v , n = 20 ):
497
+ def _list_repr_elided (v , threshold = 200 , edgeitems = 3 , indent = 0 , width = 80 ):
496
498
"""
497
499
Return a string representation for of a list where list is elided if
498
500
it has more than n elements
@@ -501,15 +503,114 @@ def _list_repr_elided(v, n=20):
501
503
----------
502
504
v : list
503
505
Input list
504
- n :
506
+ threshold :
505
507
Maximum number of elements to display
506
508
507
509
Returns
508
510
-------
509
511
str
510
512
"""
511
- if len (v ) <= n :
512
- return str (v )
513
+ if isinstance (v , list ):
514
+ open_char , close_char = '[' , ']'
515
+ elif isinstance (v , tuple ):
516
+ open_char , close_char = '(' , ')'
513
517
else :
514
- disp_v = v [:n // 2 - 1 ] + ['...' ] + v [- n // 2 + 1 :]
515
- return '[' + ', ' .join ([str (e ) for e in disp_v ]) + ']'
518
+ raise ValueError ('Invalid value of type: %s' % type (v ))
519
+
520
+ if len (v ) <= threshold :
521
+ disp_v = v
522
+ else :
523
+ disp_v = (list (v [:edgeitems ])
524
+ + ['...' ] +
525
+ list (v [- edgeitems :]))
526
+
527
+ v_str = open_char + ', ' .join ([str (e ) for e in disp_v ]) + close_char
528
+
529
+ v_wrapped = '\n ' .join (textwrap .wrap (v_str , width = width ,
530
+ initial_indent = ' ' * (indent + 1 ),
531
+ subsequent_indent = ' ' * (indent + 1 ))).strip ()
532
+ return v_wrapped
533
+
534
+
535
+ class ElidedWrapper :
536
+ """
537
+ Helper class that wraps values of certain types and produces a custom
538
+ __repr__() that may be elided and is suitable for use during pretty
539
+ printing
540
+ """
541
+ def __init__ (self , v , threshold , indent ):
542
+ self .v = v
543
+ self .indent = indent
544
+ self .threshold = threshold
545
+
546
+ @staticmethod
547
+ def is_wrappable (v ):
548
+ if (isinstance (v , (list , tuple )) and
549
+ len (v ) > 0 and
550
+ not isinstance (v [0 ], dict )):
551
+ return True
552
+ elif numpy and isinstance (v , numpy .ndarray ):
553
+ return True
554
+ elif isinstance (v , str ):
555
+ return True
556
+ else :
557
+ return False
558
+
559
+ def __repr__ (self ):
560
+ if isinstance (self .v , (list , tuple )):
561
+ # Handle lists/tuples
562
+ res = _list_repr_elided (self .v ,
563
+ threshold = self .threshold ,
564
+ indent = self .indent )
565
+ return res
566
+ elif numpy and isinstance (self .v , numpy .ndarray ):
567
+ # Handle numpy arrays
568
+
569
+ # Get original print opts
570
+ orig_opts = numpy .get_printoptions ()
571
+
572
+ # Set threshold to self.max_list_elements
573
+ numpy .set_printoptions (
574
+ ** dict (orig_opts ,
575
+ threshold = self .threshold ,
576
+ edgeitems = 3 ,
577
+ linewidth = 80 ))
578
+
579
+ res = self .v .__repr__ ()
580
+
581
+ # Add indent to all but the first line
582
+ res_lines = res .split ('\n ' )
583
+ res = ('\n ' + ' ' * self .indent ).join (res_lines )
584
+
585
+ # Restore print opts
586
+ numpy .set_printoptions (** orig_opts )
587
+ return res
588
+ elif isinstance (self .v , str ):
589
+ # Handle strings
590
+ if len (self .v ) > 80 :
591
+ return ('(' + repr (self .v [:30 ]) +
592
+ ' ... ' + repr (self .v [- 30 :]) + ')' )
593
+ else :
594
+ return self .v .__repr__ ()
595
+ else :
596
+ return self .v .__repr__ ()
597
+
598
+
599
+ class ElidedPrettyPrinter (PrettyPrinter ):
600
+ """
601
+ PrettyPrinter subclass that elides long lists/arrays/strings
602
+ """
603
+ def __init__ (self , * args , ** kwargs ):
604
+ self .threshold = kwargs .pop ('threshold' , 200 )
605
+ super ().__init__ (* args , ** kwargs )
606
+
607
+ def _format (self , val , stream , indent , allowance , context , level ):
608
+ if ElidedWrapper .is_wrappable (val ):
609
+ elided_val = ElidedWrapper (
610
+ val , self .threshold , indent )
611
+
612
+ return self ._format (
613
+ elided_val , stream , indent , allowance , context , level )
614
+ else :
615
+ return super ()._format (
616
+ val , stream , indent , allowance , context , level )
0 commit comments