1+ import collections
12import io
23import textwrap
3- import collections
4- from typing import Any
4+ from typing import Any , Generator , Union
55
6+ try :
7+ from pygments import highlight
8+ from pygments .lexers import PythonLexer
9+ from pygments .formatters import Terminal256Formatter
10+ except ImportError : # pragma: no cover
11+ pyg_lexer = pyg_formatter = None
12+ else :
13+ pyg_lexer , pyg_formatter = PythonLexer (), Terminal256Formatter (style = 'vim' )
614
715PARENTHESES_LOOKUP = [
816 (list , '[' , ']' ),
1220
1321class PrettyFormat :
1422 def __init__ (self ,
23+ colorize = False ,
1524 indent_step = 4 ,
1625 indent_char = ' ' ,
1726 repr_strings = False ,
27+ simple_cuttoff = 10 ,
28+ max_width = 120 ,
1829 yield_from_generators = True ):
1930 # TODO colours
31+ self ._colorize = colorize
2032 self ._indent_step = indent_step
2133 self ._c = indent_char
2234 self ._repr_strings = repr_strings
2335 self ._repr_generators = not yield_from_generators
36+ self ._simple_cuttoff = simple_cuttoff
37+ self ._max_width = max_width
2438 self ._type_lookup = [
2539 (dict , self ._format_dict ),
2640 ((tuple , list , set ), self ._format_list_like ),
2741 (str , self ._format_str ),
42+ (bytes , self ._format_bytes ),
2843 (collections .Generator , self ._format_generators ),
2944 ]
3045
3146 def __call__ (self , value : Any , * , indent_current : int = 0 ):
3247 self ._stream = io .StringIO ()
3348 self ._format (value , indent_current = indent_current , indent_first = True )
34- return self ._stream .getvalue ()
49+ s = self ._stream .getvalue ()
50+ if self ._colorize and pyg_lexer :
51+ s = highlight (s , lexer = pyg_lexer , formatter = pyg_formatter )
52+ return s
3553
3654 def _format (self , value : Any , indent_current : int , indent_first : bool ):
3755 if indent_first :
3856 self ._stream .write (indent_current * self ._c )
3957
40- indent_new = indent_current + self . _indent_step
41- for t , func in self ._type_lookup :
42- if isinstance ( value , t ):
43- func ( value , indent_current , indent_new )
44- return
45-
46- value_s = repr (value )
47- if ' \n ' in value_s :
48- value_s = textwrap . indent ( value_s , indent_new * self . _c ). lstrip ( ' ' )
49- self ._stream . write ( value_s )
50-
51- def _format_dict (self , value , indent_current , indent_new ):
58+ value_repr = repr ( value )
59+ if len ( value_repr ) <= self ._simple_cuttoff and not isinstance ( value , collections . Generator ) :
60+ self . _stream . write ( value_repr )
61+ else :
62+ indent_new = indent_current + self . _indent_step
63+ for t , func in self . _type_lookup :
64+ if isinstance (value , t ):
65+ func ( value , value_repr , indent_current , indent_new )
66+ return
67+ self ._format_raw ( value , value_repr , indent_current , indent_new )
68+
69+ def _format_dict (self , value : dict , value_repr : str , indent_current : int , indent_new : int ):
5270 self ._stream .write ('{\n ' )
5371 for k , v in value .items ():
5472 self ._format (k , indent_new , True )
@@ -57,7 +75,7 @@ def _format_dict(self, value, indent_current, indent_new):
5775 self ._stream .write (',\n ' )
5876 self ._stream .write (indent_current * self ._c + '}' )
5977
60- def _format_list_like (self , value , indent_current , indent_new ):
78+ def _format_list_like (self , value : Union [ list , tuple , set ], value_repr : str , indent_current : int , indent_new : int ):
6179 open_ , close_ = '(' , ')'
6280 for t , * oc in PARENTHESES_LOOKUP :
6381 if isinstance (value , t ):
@@ -70,9 +88,9 @@ def _format_list_like(self, value, indent_current, indent_new):
7088 self ._stream .write (',\n ' )
7189 self ._stream .write (indent_current * self ._c + close_ )
7290
73- def _format_str (self , value , indent_current , indent_new ):
91+ def _format_str (self , value : str , value_repr : str , indent_current : int , indent_new : int ):
7492 if self ._repr_strings :
75- self ._stream .write (repr ( value ) )
93+ self ._stream .write (value_repr )
7694 else :
7795 lines = value .splitlines (True )
7896 if len (lines ) > 1 :
@@ -82,21 +100,51 @@ def _format_str(self, value, indent_current, indent_new):
82100 self ._stream .write (prefix + repr (line ) + '\n ' )
83101 self ._stream .write (indent_current * self ._c + ')' )
84102 else :
85- self ._stream .write (repr (value ))
103+ self ._stream .write (value_repr )
104+
105+ def _format_bytes (self , value : bytes , value_repr : str , indent_current : int , indent_new : int ):
106+ wrap = self ._max_width - indent_new - 3
107+ if len (value ) < wrap :
108+ self ._stream .write (value_repr )
109+ else :
110+ self ._stream .write ('(\n ' )
111+ prefix = indent_new * self ._c
112+ start , end = 0 , wrap
113+ while start < len (value ):
114+ line = value [start :end ]
115+ self ._stream .write (prefix + repr (line ) + '\n ' )
116+ start = end
117+ end += wrap
118+ self ._stream .write (indent_current * self ._c + ')' )
86119
87- def _format_generators (self , value , indent_current , indent_new ):
120+ def _format_generators (self , value : Generator , value_repr : str , indent_current : int , indent_new : int ):
88121 if self ._repr_generators :
89- self ._stream .write (repr ( value ) )
122+ self ._stream .write (value_repr )
90123 else :
91124 self ._stream .write ('(\n ' )
92125 for v in value :
93126 self ._format (v , indent_new , True )
94127 self ._stream .write (',\n ' )
95128 self ._stream .write (indent_current * self ._c + ')' )
96129
130+ def _format_raw (self , value : Any , value_repr : str , indent_current : int , indent_new : int ):
131+ lines = value_repr .splitlines (True )
132+ if len (lines ) > 1 or (len (value_repr ) + indent_current ) >= self ._max_width :
133+ self ._stream .write ('(\n ' )
134+ wrap_at = self ._max_width - indent_new
135+ prefix = indent_new * self ._c
136+ for line in lines :
137+ sub_lines = textwrap .wrap (line , wrap_at )
138+ for sline in sub_lines :
139+ self ._stream .write (prefix + sline + '\n ' )
140+ self ._stream .write (indent_current * self ._c + ')' )
141+ else :
142+ self ._stream .write (value_repr )
143+
97144
98145pformat = PrettyFormat ()
146+ _ppformat = PrettyFormat (colorize = True )
99147
100148
101149def pprint (s ):
102- print (pformat (s ), flush = True )
150+ print (_ppformat (s ), flush = True )
0 commit comments