2121:license: Python License.
2222"""
2323from _ast import *
24+ lazy from _colorize import can_colorize , get_theme
2425
2526
2627def parse (source , filename = '<unknown>' , mode = 'exec' , * ,
@@ -117,21 +118,32 @@ def _convert_literal(node):
117118def dump (
118119 node , annotate_fields = True , include_attributes = False ,
119120 * ,
120- indent = None , show_empty = False ,
121+ color = False , indent = None , show_empty = False ,
121122):
122123 """
123124 Return a formatted dump of the tree in node. This is mainly useful for
124- debugging purposes. If annotate_fields is true (by default),
125- the returned string will show the names and the values for fields.
126- If annotate_fields is false, the result string will be more compact by
127- omitting unambiguous field names. Attributes such as line
128- numbers and column offsets are not dumped by default. If this is wanted,
129- include_attributes can be set to true. If indent is a non-negative
130- integer or string, then the tree will be pretty-printed with that indent
131- level. None (the default) selects the single line representation.
125+ debugging purposes.
126+
127+ If annotate_fields is true (by default), the returned string will show the
128+ names and the values for fields. If annotate_fields is false, the result
129+ string will be more compact by omitting unambiguous field names.
130+
131+ Attributes such as line numbers and column offsets are not dumped by default.
132+ If this is wanted, include_attributes can be set to true.
133+
134+ If color is true, the returned string is syntax highlighted using ANSI
135+ escape sequences. If color is false (the default), colored output is always
136+ disabled.
137+
138+ If indent is a non-negative integer or string, then the tree will be
139+ pretty-printed with that indent level. If indent is None (the default),
140+ the tree is dumped on a single line.
141+
132142 If show_empty is False, then empty lists and fields that are None
133143 will be omitted from the output for better readability.
134144 """
145+ t = get_theme (force_color = color , force_no_color = not color ).ast
146+
135147 def _format (node , level = 0 ):
136148 if indent is not None :
137149 level += 1
@@ -166,15 +178,17 @@ def _format(node, level=0):
166178 field_type = cls ._field_types .get (name , object )
167179 if field_type is expr_context :
168180 if not keywords :
169- args_buffer .append (repr (value ))
181+ args_buffer .append (
182+ f'{ t .node } { type (value ).__name__ } '
183+ f'{ t .reset } ()' )
170184 continue
171185 if not keywords :
172186 args .extend (args_buffer )
173187 args_buffer = []
174188 value , simple = _format (value , level )
175189 allsimple = allsimple and simple
176190 if keywords :
177- args .append ('%s=%s' % ( name , value ) )
191+ args .append (f' { t . field } { name } { t . reset } = { value } ' )
178192 else :
179193 args .append (value )
180194 if include_attributes and node ._attributes :
@@ -187,14 +201,21 @@ def _format(node, level=0):
187201 continue
188202 value , simple = _format (value , level )
189203 allsimple = allsimple and simple
190- args .append ('%s=%s' % (name , value ))
204+ args .append (f'{ t .attribute } { name } { t .reset } ={ value } ' )
205+ cls_name = f'{ t .node } { cls .__name__ } { t .reset } '
191206 if allsimple and len (args ) <= 3 :
192- return '%s(%s)' % ( node . __class__ . __name__ , ', ' .join (args )) , not args
193- return '%s(%s%s)' % ( node . __class__ . __name__ , prefix , sep .join (args )) , False
207+ return f' { cls_name } ( { ", " .join (args )} )' , not args
208+ return f' { cls_name } ( { prefix } { sep .join (args )} )' , False
194209 elif isinstance (node , list ):
195210 if not node :
196211 return '[]' , True
197212 return '[%s%s]' % (prefix , sep .join (_format (x , level )[0 ] for x in node )), False
213+ if isinstance (node , bool ) or node is None or node is Ellipsis :
214+ return f'{ t .keyword } { node !r} { t .reset } ' , True
215+ if isinstance (node , (int , float , complex )):
216+ return f'{ t .number } { node !r} { t .reset } ' , True
217+ if isinstance (node , (str , bytes )):
218+ return f'{ t .string } { node !r} { t .reset } ' , True
198219 return repr (node ), True
199220
200221 if not isinstance (node , AST ):
@@ -642,7 +663,7 @@ def main(args=None):
642663 import argparse
643664 import sys
644665
645- parser = argparse .ArgumentParser (color = True )
666+ parser = argparse .ArgumentParser (formatter_class = argparse . ArgumentDefaultsHelpFormatter )
646667 parser .add_argument ('infile' , nargs = '?' , default = '-' ,
647668 help = 'the file to parse; defaults to stdin' )
648669 parser .add_argument ('-m' , '--mode' , default = 'exec' ,
@@ -661,7 +682,7 @@ def main(args=None):
661682 '(for example, 3.10)' )
662683 parser .add_argument ('-O' , '--optimize' ,
663684 type = int , default = - 1 , metavar = 'LEVEL' ,
664- help = 'optimization level for parser (default -1) ' )
685+ help = 'optimization level for parser' )
665686 parser .add_argument ('--show-empty' , default = False , action = 'store_true' ,
666687 help = 'show empty lists and fields in dump output' )
667688 args = parser .parse_args (args )
@@ -688,6 +709,7 @@ def main(args=None):
688709 tree = parse (source , name , args .mode , type_comments = args .no_type_comments ,
689710 feature_version = feature_version , optimize = args .optimize )
690711 print (dump (tree , include_attributes = args .include_attributes ,
712+ color = can_colorize (file = sys .stdout ),
691713 indent = args .indent , show_empty = args .show_empty ))
692714
693715if __name__ == '__main__' :
0 commit comments