gh-116023: Add show_empty=False to ast.dump (#116037)

Co-authored-by: Carl Meyer <carl@oddbird.net>
This commit is contained in:
Nikita Sobolev 2024-04-24 11:02:38 +03:00 committed by GitHub
parent 7e87d30f1f
commit 692e902c74
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 249 additions and 167 deletions

View file

@ -173,8 +173,7 @@ Root nodes
Assign( Assign(
targets=[ targets=[
Name(id='x', ctx=Store())], Name(id='x', ctx=Store())],
value=Constant(value=1))], value=Constant(value=1))])
type_ignores=[])
.. class:: Expression(body) .. class:: Expression(body)
@ -302,8 +301,7 @@ Literals
value=Call( value=Call(
func=Name(id='sin', ctx=Load()), func=Name(id='sin', ctx=Load()),
args=[ args=[
Name(id='a', ctx=Load())], Name(id='a', ctx=Load())]),
keywords=[]),
conversion=-1, conversion=-1,
format_spec=JoinedStr( format_spec=JoinedStr(
values=[ values=[
@ -398,8 +396,7 @@ Variables
Module( Module(
body=[ body=[
Expr( Expr(
value=Name(id='a', ctx=Load()))], value=Name(id='a', ctx=Load()))])
type_ignores=[])
>>> print(ast.dump(ast.parse('a = 1'), indent=4)) >>> print(ast.dump(ast.parse('a = 1'), indent=4))
Module( Module(
@ -407,16 +404,14 @@ Variables
Assign( Assign(
targets=[ targets=[
Name(id='a', ctx=Store())], Name(id='a', ctx=Store())],
value=Constant(value=1))], value=Constant(value=1))])
type_ignores=[])
>>> print(ast.dump(ast.parse('del a'), indent=4)) >>> print(ast.dump(ast.parse('del a'), indent=4))
Module( Module(
body=[ body=[
Delete( Delete(
targets=[ targets=[
Name(id='a', ctx=Del())])], Name(id='a', ctx=Del())])])
type_ignores=[])
.. class:: Starred(value, ctx) .. class:: Starred(value, ctx)
@ -439,8 +434,7 @@ Variables
value=Name(id='b', ctx=Store()), value=Name(id='b', ctx=Store()),
ctx=Store())], ctx=Store())],
ctx=Store())], ctx=Store())],
value=Name(id='it', ctx=Load()))], value=Name(id='it', ctx=Load()))])
type_ignores=[])
.. _ast-expressions: .. _ast-expressions:
@ -463,8 +457,7 @@ Expressions
Expr( Expr(
value=UnaryOp( value=UnaryOp(
op=USub(), op=USub(),
operand=Name(id='a', ctx=Load())))], operand=Name(id='a', ctx=Load())))])
type_ignores=[])
.. class:: UnaryOp(op, operand) .. class:: UnaryOp(op, operand)
@ -729,7 +722,10 @@ Comprehensions
.. doctest:: .. doctest::
>>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4)) >>> print(ast.dump(
... ast.parse('[x for x in numbers]', mode='eval'),
... indent=4,
... ))
Expression( Expression(
body=ListComp( body=ListComp(
elt=Name(id='x', ctx=Load()), elt=Name(id='x', ctx=Load()),
@ -737,9 +733,11 @@ Comprehensions
comprehension( comprehension(
target=Name(id='x', ctx=Store()), target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()), iter=Name(id='numbers', ctx=Load()),
ifs=[],
is_async=0)])) is_async=0)]))
>>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4)) >>> print(ast.dump(
... ast.parse('{x: x**2 for x in numbers}', mode='eval'),
... indent=4,
... ))
Expression( Expression(
body=DictComp( body=DictComp(
key=Name(id='x', ctx=Load()), key=Name(id='x', ctx=Load()),
@ -751,9 +749,11 @@ Comprehensions
comprehension( comprehension(
target=Name(id='x', ctx=Store()), target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()), iter=Name(id='numbers', ctx=Load()),
ifs=[],
is_async=0)])) is_async=0)]))
>>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4)) >>> print(ast.dump(
... ast.parse('{x for x in numbers}', mode='eval'),
... indent=4,
... ))
Expression( Expression(
body=SetComp( body=SetComp(
elt=Name(id='x', ctx=Load()), elt=Name(id='x', ctx=Load()),
@ -761,7 +761,6 @@ Comprehensions
comprehension( comprehension(
target=Name(id='x', ctx=Store()), target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()), iter=Name(id='numbers', ctx=Load()),
ifs=[],
is_async=0)])) is_async=0)]))
@ -784,18 +783,15 @@ Comprehensions
elt=Call( elt=Call(
func=Name(id='ord', ctx=Load()), func=Name(id='ord', ctx=Load()),
args=[ args=[
Name(id='c', ctx=Load())], Name(id='c', ctx=Load())]),
keywords=[]),
generators=[ generators=[
comprehension( comprehension(
target=Name(id='line', ctx=Store()), target=Name(id='line', ctx=Store()),
iter=Name(id='file', ctx=Load()), iter=Name(id='file', ctx=Load()),
ifs=[],
is_async=0), is_async=0),
comprehension( comprehension(
target=Name(id='c', ctx=Store()), target=Name(id='c', ctx=Store()),
iter=Name(id='line', ctx=Load()), iter=Name(id='line', ctx=Load()),
ifs=[],
is_async=0)])) is_async=0)]))
>>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'), >>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'),
@ -834,7 +830,6 @@ Comprehensions
comprehension( comprehension(
target=Name(id='i', ctx=Store()), target=Name(id='i', ctx=Store()),
iter=Name(id='soc', ctx=Load()), iter=Name(id='soc', ctx=Load()),
ifs=[],
is_async=1)])) is_async=1)]))
@ -864,8 +859,7 @@ Statements
targets=[ targets=[
Name(id='a', ctx=Store()), Name(id='a', ctx=Store()),
Name(id='b', ctx=Store())], Name(id='b', ctx=Store())],
value=Constant(value=1))], value=Constant(value=1))])
type_ignores=[])
>>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking >>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking
Module( Module(
@ -877,8 +871,7 @@ Statements
Name(id='a', ctx=Store()), Name(id='a', ctx=Store()),
Name(id='b', ctx=Store())], Name(id='b', ctx=Store())],
ctx=Store())], ctx=Store())],
value=Name(id='c', ctx=Load()))], value=Name(id='c', ctx=Load()))])
type_ignores=[])
.. class:: AnnAssign(target, annotation, value, simple) .. class:: AnnAssign(target, annotation, value, simple)
@ -898,8 +891,7 @@ Statements
AnnAssign( AnnAssign(
target=Name(id='c', ctx=Store()), target=Name(id='c', ctx=Store()),
annotation=Name(id='int', ctx=Load()), annotation=Name(id='int', ctx=Load()),
simple=1)], simple=1)])
type_ignores=[])
>>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis >>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis
Module( Module(
@ -908,8 +900,7 @@ Statements
target=Name(id='a', ctx=Store()), target=Name(id='a', ctx=Store()),
annotation=Name(id='int', ctx=Load()), annotation=Name(id='int', ctx=Load()),
value=Constant(value=1), value=Constant(value=1),
simple=0)], simple=0)])
type_ignores=[])
>>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation >>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation
Module( Module(
@ -920,8 +911,7 @@ Statements
attr='b', attr='b',
ctx=Store()), ctx=Store()),
annotation=Name(id='int', ctx=Load()), annotation=Name(id='int', ctx=Load()),
simple=0)], simple=0)])
type_ignores=[])
>>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation >>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation
Module( Module(
@ -932,8 +922,7 @@ Statements
slice=Constant(value=1), slice=Constant(value=1),
ctx=Store()), ctx=Store()),
annotation=Name(id='int', ctx=Load()), annotation=Name(id='int', ctx=Load()),
simple=0)], simple=0)])
type_ignores=[])
.. class:: AugAssign(target, op, value) .. class:: AugAssign(target, op, value)
@ -954,8 +943,7 @@ Statements
AugAssign( AugAssign(
target=Name(id='x', ctx=Store()), target=Name(id='x', ctx=Store()),
op=Add(), op=Add(),
value=Constant(value=2))], value=Constant(value=2))])
type_ignores=[])
.. class:: Raise(exc, cause) .. class:: Raise(exc, cause)
@ -971,8 +959,7 @@ Statements
body=[ body=[
Raise( Raise(
exc=Name(id='x', ctx=Load()), exc=Name(id='x', ctx=Load()),
cause=Name(id='y', ctx=Load()))], cause=Name(id='y', ctx=Load()))])
type_ignores=[])
.. class:: Assert(test, msg) .. class:: Assert(test, msg)
@ -987,8 +974,7 @@ Statements
body=[ body=[
Assert( Assert(
test=Name(id='x', ctx=Load()), test=Name(id='x', ctx=Load()),
msg=Name(id='y', ctx=Load()))], msg=Name(id='y', ctx=Load()))])
type_ignores=[])
.. class:: Delete(targets) .. class:: Delete(targets)
@ -1005,8 +991,7 @@ Statements
targets=[ targets=[
Name(id='x', ctx=Del()), Name(id='x', ctx=Del()),
Name(id='y', ctx=Del()), Name(id='y', ctx=Del()),
Name(id='z', ctx=Del())])], Name(id='z', ctx=Del())])])
type_ignores=[])
.. class:: Pass() .. class:: Pass()
@ -1018,8 +1003,7 @@ Statements
>>> print(ast.dump(ast.parse('pass'), indent=4)) >>> print(ast.dump(ast.parse('pass'), indent=4))
Module( Module(
body=[ body=[
Pass()], Pass()])
type_ignores=[])
.. class:: TypeAlias(name, type_params, value) .. class:: TypeAlias(name, type_params, value)
@ -1036,9 +1020,7 @@ Statements
body=[ body=[
TypeAlias( TypeAlias(
name=Name(id='Alias', ctx=Store()), name=Name(id='Alias', ctx=Store()),
type_params=[], value=Name(id='int', ctx=Load()))])
value=Name(id='int', ctx=Load()))],
type_ignores=[])
.. versionadded:: 3.12 .. versionadded:: 3.12
@ -1061,8 +1043,7 @@ Imports
names=[ names=[
alias(name='x'), alias(name='x'),
alias(name='y'), alias(name='y'),
alias(name='z')])], alias(name='z')])])
type_ignores=[])
.. class:: ImportFrom(module, names, level) .. class:: ImportFrom(module, names, level)
@ -1083,8 +1064,7 @@ Imports
alias(name='x'), alias(name='x'),
alias(name='y'), alias(name='y'),
alias(name='z')], alias(name='z')],
level=0)], level=0)])
type_ignores=[])
.. class:: alias(name, asname) .. class:: alias(name, asname)
@ -1102,8 +1082,7 @@ Imports
names=[ names=[
alias(name='a', asname='b'), alias(name='a', asname='b'),
alias(name='c')], alias(name='c')],
level=2)], level=2)])
type_ignores=[])
Control flow Control flow
^^^^^^^^^^^^ ^^^^^^^^^^^^
@ -1146,8 +1125,7 @@ Control flow
value=Constant(value=Ellipsis))], value=Constant(value=Ellipsis))],
orelse=[ orelse=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. class:: For(target, iter, body, orelse, type_comment) .. class:: For(target, iter, body, orelse, type_comment)
@ -1181,8 +1159,7 @@ Control flow
value=Constant(value=Ellipsis))], value=Constant(value=Ellipsis))],
orelse=[ orelse=[
Expr( Expr(
value=Constant(value=Ellipsis))])], value=Constant(value=Ellipsis))])])
type_ignores=[])
.. class:: While(test, body, orelse) .. class:: While(test, body, orelse)
@ -1207,8 +1184,7 @@ Control flow
value=Constant(value=Ellipsis))], value=Constant(value=Ellipsis))],
orelse=[ orelse=[
Expr( Expr(
value=Constant(value=Ellipsis))])], value=Constant(value=Ellipsis))])])
type_ignores=[])
.. class:: Break .. class:: Break
@ -1242,9 +1218,7 @@ Control flow
body=[ body=[
Break()], Break()],
orelse=[ orelse=[
Continue()])], Continue()])])])
orelse=[])],
type_ignores=[])
.. class:: Try(body, handlers, orelse, finalbody) .. class:: Try(body, handlers, orelse, finalbody)
@ -1289,8 +1263,7 @@ Control flow
value=Constant(value=Ellipsis))], value=Constant(value=Ellipsis))],
finalbody=[ finalbody=[
Expr( Expr(
value=Constant(value=Ellipsis))])], value=Constant(value=Ellipsis))])])
type_ignores=[])
.. class:: TryStar(body, handlers, orelse, finalbody) .. class:: TryStar(body, handlers, orelse, finalbody)
@ -1318,10 +1291,7 @@ Control flow
type=Name(id='Exception', ctx=Load()), type=Name(id='Exception', ctx=Load()),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])], value=Constant(value=Ellipsis))])])])
orelse=[],
finalbody=[])],
type_ignores=[])
.. versionadded:: 3.11 .. versionadded:: 3.11
@ -1353,10 +1323,7 @@ Control flow
ExceptHandler( ExceptHandler(
type=Name(id='TypeError', ctx=Load()), type=Name(id='TypeError', ctx=Load()),
body=[ body=[
Pass()])], Pass()])])])
orelse=[],
finalbody=[])],
type_ignores=[])
.. class:: With(items, body, type_comment) .. class:: With(items, body, type_comment)
@ -1398,9 +1365,7 @@ Control flow
func=Name(id='something', ctx=Load()), func=Name(id='something', ctx=Load()),
args=[ args=[
Name(id='b', ctx=Load()), Name(id='b', ctx=Load()),
Name(id='d', ctx=Load())], Name(id='d', ctx=Load())]))])])
keywords=[]))])],
type_ignores=[])
Pattern matching Pattern matching
@ -1457,14 +1422,10 @@ Pattern matching
value=Constant(value=Ellipsis))]), value=Constant(value=Ellipsis))]),
match_case( match_case(
pattern=MatchClass( pattern=MatchClass(
cls=Name(id='tuple', ctx=Load()), cls=Name(id='tuple', ctx=Load())),
patterns=[],
kwd_attrs=[],
kwd_patterns=[]),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1492,8 +1453,7 @@ Pattern matching
value=Constant(value='Relevant')), value=Constant(value='Relevant')),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1519,8 +1479,7 @@ Pattern matching
pattern=MatchSingleton(value=None), pattern=MatchSingleton(value=None),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1552,8 +1511,7 @@ Pattern matching
value=Constant(value=2))]), value=Constant(value=2))]),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1594,8 +1552,7 @@ Pattern matching
MatchStar()]), MatchStar()]),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1639,11 +1596,10 @@ Pattern matching
Expr( Expr(
value=Constant(value=Ellipsis))]), value=Constant(value=Ellipsis))]),
match_case( match_case(
pattern=MatchMapping(keys=[], patterns=[], rest='rest'), pattern=MatchMapping(rest='rest'),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1685,16 +1641,13 @@ Pattern matching
MatchValue( MatchValue(
value=Constant(value=0)), value=Constant(value=0)),
MatchValue( MatchValue(
value=Constant(value=0))], value=Constant(value=0))]),
kwd_attrs=[],
kwd_patterns=[]),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))]), value=Constant(value=Ellipsis))]),
match_case( match_case(
pattern=MatchClass( pattern=MatchClass(
cls=Name(id='Point3D', ctx=Load()), cls=Name(id='Point3D', ctx=Load()),
patterns=[],
kwd_attrs=[ kwd_attrs=[
'x', 'x',
'y', 'y',
@ -1708,8 +1661,7 @@ Pattern matching
value=Constant(value=0))]), value=Constant(value=0))]),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1751,8 +1703,7 @@ Pattern matching
pattern=MatchAs(), pattern=MatchAs(),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1785,8 +1736,7 @@ Pattern matching
MatchAs(name='y')]), MatchAs(name='y')]),
body=[ body=[
Expr( Expr(
value=Constant(value=Ellipsis))])])], value=Constant(value=Ellipsis))])])])
type_ignores=[])
.. versionadded:: 3.10 .. versionadded:: 3.10
@ -1818,8 +1768,7 @@ aliases.
value=Subscript( value=Subscript(
value=Name(id='list', ctx=Load()), value=Name(id='list', ctx=Load()),
slice=Name(id='T', ctx=Load()), slice=Name(id='T', ctx=Load()),
ctx=Load()))], ctx=Load()))])
type_ignores=[])
.. versionadded:: 3.12 .. versionadded:: 3.12
@ -1843,8 +1792,7 @@ aliases.
Name(id='P', ctx=Load()), Name(id='P', ctx=Load()),
Name(id='int', ctx=Load())], Name(id='int', ctx=Load())],
ctx=Load()), ctx=Load()),
ctx=Load()))], ctx=Load()))])
type_ignores=[])
.. versionadded:: 3.12 .. versionadded:: 3.12
@ -1869,8 +1817,7 @@ aliases.
value=Name(id='Ts', ctx=Load()), value=Name(id='Ts', ctx=Load()),
ctx=Load())], ctx=Load())],
ctx=Load()), ctx=Load()),
ctx=Load()))], ctx=Load()))])
type_ignores=[])
.. versionadded:: 3.12 .. versionadded:: 3.12
@ -1910,15 +1857,10 @@ Function and class definitions
Expr( Expr(
value=Lambda( value=Lambda(
args=arguments( args=arguments(
posonlyargs=[],
args=[ args=[
arg(arg='x'), arg(arg='x'),
arg(arg='y')], arg(arg='y')]),
kwonlyargs=[], body=Constant(value=Ellipsis)))])
kw_defaults=[],
defaults=[]),
body=Constant(value=Ellipsis)))],
type_ignores=[])
.. class:: arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults) .. class:: arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)
@ -1957,7 +1899,6 @@ Function and class definitions
FunctionDef( FunctionDef(
name='f', name='f',
args=arguments( args=arguments(
posonlyargs=[],
args=[ args=[
arg( arg(
arg='a', arg='a',
@ -1980,9 +1921,7 @@ Function and class definitions
decorator_list=[ decorator_list=[
Name(id='decorator1', ctx=Load()), Name(id='decorator1', ctx=Load()),
Name(id='decorator2', ctx=Load())], Name(id='decorator2', ctx=Load())],
returns=Constant(value='return annotation'), returns=Constant(value='return annotation'))])
type_params=[])],
type_ignores=[])
.. class:: Return(value) .. class:: Return(value)
@ -1995,8 +1934,7 @@ Function and class definitions
Module( Module(
body=[ body=[
Return( Return(
value=Constant(value=4))], value=Constant(value=4))])
type_ignores=[])
.. class:: Yield(value) .. class:: Yield(value)
@ -2012,16 +1950,14 @@ Function and class definitions
body=[ body=[
Expr( Expr(
value=Yield( value=Yield(
value=Name(id='x', ctx=Load())))], value=Name(id='x', ctx=Load())))])
type_ignores=[])
>>> print(ast.dump(ast.parse('yield from x'), indent=4)) >>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module( Module(
body=[ body=[
Expr( Expr(
value=YieldFrom( value=YieldFrom(
value=Name(id='x', ctx=Load())))], value=Name(id='x', ctx=Load())))])
type_ignores=[])
.. class:: Global(names) .. class:: Global(names)
@ -2038,8 +1974,7 @@ Function and class definitions
names=[ names=[
'x', 'x',
'y', 'y',
'z'])], 'z'])])
type_ignores=[])
>>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4))
Module( Module(
@ -2048,8 +1983,7 @@ Function and class definitions
names=[ names=[
'x', 'x',
'y', 'y',
'z'])], 'z'])])
type_ignores=[])
.. class:: ClassDef(name, bases, keywords, body, decorator_list, type_params) .. class:: ClassDef(name, bases, keywords, body, decorator_list, type_params)
@ -2089,9 +2023,7 @@ Function and class definitions
Pass()], Pass()],
decorator_list=[ decorator_list=[
Name(id='decorator1', ctx=Load()), Name(id='decorator1', ctx=Load()),
Name(id='decorator2', ctx=Load())], Name(id='decorator2', ctx=Load())])])
type_params=[])],
type_ignores=[])
.. versionchanged:: 3.12 .. versionchanged:: 3.12
Added ``type_params``. Added ``type_params``.
@ -2123,22 +2055,12 @@ Async and await
body=[ body=[
AsyncFunctionDef( AsyncFunctionDef(
name='f', name='f',
args=arguments( args=arguments(),
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[ body=[
Expr( Expr(
value=Await( value=Await(
value=Call( value=Call(
func=Name(id='other_func', ctx=Load()), func=Name(id='other_func', ctx=Load()))))])])
args=[],
keywords=[])))],
decorator_list=[],
type_params=[])],
type_ignores=[])
.. class:: AsyncFor(target, iter, body, orelse, type_comment) .. class:: AsyncFor(target, iter, body, orelse, type_comment)
@ -2425,7 +2347,7 @@ and classes for traversing abstract syntax trees:
node = YourTransformer().visit(node) node = YourTransformer().visit(node)
.. function:: dump(node, annotate_fields=True, include_attributes=False, *, indent=None) .. function:: dump(node, annotate_fields=True, include_attributes=False, *, indent=None, show_empty=False)
Return a formatted dump of the tree in *node*. This is mainly useful for Return a formatted dump of the tree in *node*. This is mainly useful for
debugging purposes. If *annotate_fields* is true (by default), debugging purposes. If *annotate_fields* is true (by default),
@ -2442,9 +2364,42 @@ and classes for traversing abstract syntax trees:
indents that many spaces per level. If *indent* is a string (such as ``"\t"``), indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
that string is used to indent each level. that string is used to indent each level.
If *show_empty* is ``False`` (the default), empty lists and fields that are ``None``
will be omitted from the output.
.. versionchanged:: 3.9 .. versionchanged:: 3.9
Added the *indent* option. Added the *indent* option.
.. versionchanged:: 3.13
Added the *show_empty* option.
.. doctest::
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4, show_empty=True))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()),
args=[],
keywords=[])))],
decorator_list=[],
type_params=[])],
type_ignores=[])
.. _ast-compiler-flags: .. _ast-compiler-flags:

View file

@ -114,7 +114,11 @@ def literal_eval(node_or_string):
return _convert(node_or_string) return _convert(node_or_string)
def dump(node, annotate_fields=True, include_attributes=False, *, indent=None): def dump(
node, annotate_fields=True, include_attributes=False,
*,
indent=None, show_empty=False,
):
""" """
Return a formatted dump of the tree in node. This is mainly useful for Return a formatted dump of the tree in node. This is mainly useful for
debugging purposes. If annotate_fields is true (by default), debugging purposes. If annotate_fields is true (by default),
@ -125,6 +129,8 @@ def dump(node, annotate_fields=True, include_attributes=False, *, indent=None):
include_attributes can be set to true. If indent is a non-negative include_attributes can be set to true. If indent is a non-negative
integer or string, then the tree will be pretty-printed with that indent integer or string, then the tree will be pretty-printed with that indent
level. None (the default) selects the single line representation. level. None (the default) selects the single line representation.
If show_empty is False, then empty lists and fields that are None
will be omitted from the output for better readability.
""" """
def _format(node, level=0): def _format(node, level=0):
if indent is not None: if indent is not None:
@ -137,6 +143,7 @@ def dump(node, annotate_fields=True, include_attributes=False, *, indent=None):
if isinstance(node, AST): if isinstance(node, AST):
cls = type(node) cls = type(node)
args = [] args = []
args_buffer = []
allsimple = True allsimple = True
keywords = annotate_fields keywords = annotate_fields
for name in node._fields: for name in node._fields:
@ -148,6 +155,18 @@ def dump(node, annotate_fields=True, include_attributes=False, *, indent=None):
if value is None and getattr(cls, name, ...) is None: if value is None and getattr(cls, name, ...) is None:
keywords = True keywords = True
continue continue
if (
not show_empty
and (value is None or value == [])
# Special cases:
# `Constant(value=None)` and `MatchSingleton(value=None)`
and not isinstance(node, (Constant, MatchSingleton))
):
args_buffer.append(repr(value))
continue
elif not keywords:
args.extend(args_buffer)
args_buffer = []
value, simple = _format(value, level) value, simple = _format(value, level)
allsimple = allsimple and simple allsimple = allsimple and simple
if keywords: if keywords:

View file

@ -1227,21 +1227,20 @@ class ASTHelpers_Test(unittest.TestCase):
node = ast.parse('spam(eggs, "and cheese")') node = ast.parse('spam(eggs, "and cheese")')
self.assertEqual(ast.dump(node), self.assertEqual(ast.dump(node),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), "
"args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')], " "args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')]))])"
"keywords=[]))], type_ignores=[])"
) )
self.assertEqual(ast.dump(node, annotate_fields=False), self.assertEqual(ast.dump(node, annotate_fields=False),
"Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), "
"Constant('and cheese')], []))], [])" "Constant('and cheese')]))])"
) )
self.assertEqual(ast.dump(node, include_attributes=True), self.assertEqual(ast.dump(node, include_attributes=True),
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=4), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=4), "
"args=[Name(id='eggs', ctx=Load(), lineno=1, col_offset=5, " "args=[Name(id='eggs', ctx=Load(), lineno=1, col_offset=5, "
"end_lineno=1, end_col_offset=9), Constant(value='and cheese', " "end_lineno=1, end_col_offset=9), Constant(value='and cheese', "
"lineno=1, col_offset=11, end_lineno=1, end_col_offset=23)], keywords=[], " "lineno=1, col_offset=11, end_lineno=1, end_col_offset=23)], "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=24), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24), "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)], type_ignores=[])" "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)])"
) )
def test_dump_indent(self): def test_dump_indent(self):
@ -1254,9 +1253,7 @@ Module(
func=Name(id='spam', ctx=Load()), func=Name(id='spam', ctx=Load()),
args=[ args=[
Name(id='eggs', ctx=Load()), Name(id='eggs', ctx=Load()),
Constant(value='and cheese')], Constant(value='and cheese')]))])""")
keywords=[]))],
type_ignores=[])""")
self.assertEqual(ast.dump(node, annotate_fields=False, indent='\t'), """\ self.assertEqual(ast.dump(node, annotate_fields=False, indent='\t'), """\
Module( Module(
\t[ \t[
@ -1265,9 +1262,7 @@ Module(
\t\t\t\tName('spam', Load()), \t\t\t\tName('spam', Load()),
\t\t\t\t[ \t\t\t\t[
\t\t\t\t\tName('eggs', Load()), \t\t\t\t\tName('eggs', Load()),
\t\t\t\t\tConstant('and cheese')], \t\t\t\t\tConstant('and cheese')]))])""")
\t\t\t\t[]))],
\t[])""")
self.assertEqual(ast.dump(node, include_attributes=True, indent=3), """\ self.assertEqual(ast.dump(node, include_attributes=True, indent=3), """\
Module( Module(
body=[ body=[
@ -1294,7 +1289,6 @@ Module(
col_offset=11, col_offset=11,
end_lineno=1, end_lineno=1,
end_col_offset=23)], end_col_offset=23)],
keywords=[],
lineno=1, lineno=1,
col_offset=0, col_offset=0,
end_lineno=1, end_lineno=1,
@ -1302,8 +1296,7 @@ Module(
lineno=1, lineno=1,
col_offset=0, col_offset=0,
end_lineno=1, end_lineno=1,
end_col_offset=24)], end_col_offset=24)])""")
type_ignores=[])""")
def test_dump_incomplete(self): def test_dump_incomplete(self):
node = ast.Raise(lineno=3, col_offset=4) node = ast.Raise(lineno=3, col_offset=4)
@ -1333,6 +1326,119 @@ Module(
self.assertEqual(ast.dump(node, annotate_fields=False), self.assertEqual(ast.dump(node, annotate_fields=False),
"Raise(cause=Name('e', Load()))" "Raise(cause=Name('e', Load()))"
) )
# Arguments:
node = ast.arguments(args=[ast.arg("x")])
self.assertEqual(ast.dump(node, annotate_fields=False),
"arguments([], [arg('x')])",
)
node = ast.arguments(posonlyargs=[ast.arg("x")])
self.assertEqual(ast.dump(node, annotate_fields=False),
"arguments([arg('x')])",
)
node = ast.arguments(posonlyargs=[ast.arg("x")], kwonlyargs=[ast.arg('y')])
self.assertEqual(ast.dump(node, annotate_fields=False),
"arguments([arg('x')], kwonlyargs=[arg('y')])",
)
node = ast.arguments(args=[ast.arg("x")], kwonlyargs=[ast.arg('y')])
self.assertEqual(ast.dump(node, annotate_fields=False),
"arguments([], [arg('x')], kwonlyargs=[arg('y')])",
)
node = ast.arguments()
self.assertEqual(ast.dump(node, annotate_fields=False),
"arguments()",
)
# Classes:
node = ast.ClassDef(
'T',
[],
[ast.keyword('a', ast.Constant(None))],
[],
[ast.Name('dataclass')],
)
self.assertEqual(ast.dump(node),
"ClassDef(name='T', keywords=[keyword(arg='a', value=Constant(value=None))], decorator_list=[Name(id='dataclass')])",
)
self.assertEqual(ast.dump(node, annotate_fields=False),
"ClassDef('T', [], [keyword('a', Constant(None))], [], [Name('dataclass')])",
)
def test_dump_show_empty(self):
def check_node(node, empty, full, **kwargs):
with self.subTest(show_empty=False):
self.assertEqual(
ast.dump(node, show_empty=False, **kwargs),
empty,
)
with self.subTest(show_empty=True):
self.assertEqual(
ast.dump(node, show_empty=True, **kwargs),
full,
)
def check_text(code, empty, full, **kwargs):
check_node(ast.parse(code), empty, full, **kwargs)
check_node(
ast.arguments(),
empty="arguments()",
full="arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[])",
)
check_node(
# Corner case: there are no real `Name` instances with `id=''`:
ast.Name(id='', ctx=ast.Load()),
empty="Name(id='', ctx=Load())",
full="Name(id='', ctx=Load())",
)
check_node(
ast.MatchSingleton(value=None),
empty="MatchSingleton(value=None)",
full="MatchSingleton(value=None)",
)
check_node(
ast.Constant(value=None),
empty="Constant(value=None)",
full="Constant(value=None)",
)
check_node(
ast.Constant(value=''),
empty="Constant(value='')",
full="Constant(value='')",
)
check_text(
"def a(b: int = 0, *, c): ...",
empty="Module(body=[FunctionDef(name='a', args=arguments(args=[arg(arg='b', annotation=Name(id='int', ctx=Load()))], kwonlyargs=[arg(arg='c')], kw_defaults=[None], defaults=[Constant(value=0)]), body=[Expr(value=Constant(value=Ellipsis))])])",
full="Module(body=[FunctionDef(name='a', args=arguments(posonlyargs=[], args=[arg(arg='b', annotation=Name(id='int', ctx=Load()))], kwonlyargs=[arg(arg='c')], kw_defaults=[None], defaults=[Constant(value=0)]), body=[Expr(value=Constant(value=Ellipsis))], decorator_list=[], type_params=[])], type_ignores=[])",
)
check_text(
"def a(b: int = 0, *, c): ...",
empty="Module(body=[FunctionDef(name='a', args=arguments(args=[arg(arg='b', annotation=Name(id='int', ctx=Load(), lineno=1, col_offset=9, end_lineno=1, end_col_offset=12), lineno=1, col_offset=6, end_lineno=1, end_col_offset=12)], kwonlyargs=[arg(arg='c', lineno=1, col_offset=21, end_lineno=1, end_col_offset=22)], kw_defaults=[None], defaults=[Constant(value=0, lineno=1, col_offset=15, end_lineno=1, end_col_offset=16)]), body=[Expr(value=Constant(value=Ellipsis, lineno=1, col_offset=25, end_lineno=1, end_col_offset=28), lineno=1, col_offset=25, end_lineno=1, end_col_offset=28)], lineno=1, col_offset=0, end_lineno=1, end_col_offset=28)])",
full="Module(body=[FunctionDef(name='a', args=arguments(posonlyargs=[], args=[arg(arg='b', annotation=Name(id='int', ctx=Load(), lineno=1, col_offset=9, end_lineno=1, end_col_offset=12), lineno=1, col_offset=6, end_lineno=1, end_col_offset=12)], kwonlyargs=[arg(arg='c', lineno=1, col_offset=21, end_lineno=1, end_col_offset=22)], kw_defaults=[None], defaults=[Constant(value=0, lineno=1, col_offset=15, end_lineno=1, end_col_offset=16)]), body=[Expr(value=Constant(value=Ellipsis, lineno=1, col_offset=25, end_lineno=1, end_col_offset=28), lineno=1, col_offset=25, end_lineno=1, end_col_offset=28)], decorator_list=[], type_params=[], lineno=1, col_offset=0, end_lineno=1, end_col_offset=28)], type_ignores=[])",
include_attributes=True,
)
check_text(
'spam(eggs, "and cheese")',
empty="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')]))])",
full="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')], keywords=[]))], type_ignores=[])",
)
check_text(
'spam(eggs, text="and cheese")',
empty="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load())], keywords=[keyword(arg='text', value=Constant(value='and cheese'))]))])",
full="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load())], keywords=[keyword(arg='text', value=Constant(value='and cheese'))]))], type_ignores=[])",
)
check_text(
"import _ast as ast; from module import sub",
empty="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)])",
full="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)], type_ignores=[])",
)
def test_copy_location(self): def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval') src = ast.parse('1 + 1', mode='eval')
@ -1361,14 +1467,13 @@ Module(
"Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), " "Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=5), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=5), "
"args=[Constant(value='spam', lineno=1, col_offset=6, end_lineno=1, " "args=[Constant(value='spam', lineno=1, col_offset=6, end_lineno=1, "
"end_col_offset=12)], keywords=[], lineno=1, col_offset=0, end_lineno=1, " "end_col_offset=12)], lineno=1, col_offset=0, end_lineno=1, "
"end_col_offset=13), lineno=1, col_offset=0, end_lineno=1, " "end_col_offset=13), lineno=1, col_offset=0, end_lineno=1, "
"end_col_offset=13), Expr(value=Call(func=Name(id='spam', ctx=Load(), " "end_col_offset=13), Expr(value=Call(func=Name(id='spam', ctx=Load(), "
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=0), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=0), "
"args=[Constant(value='eggs', lineno=1, col_offset=0, end_lineno=1, " "args=[Constant(value='eggs', lineno=1, col_offset=0, end_lineno=1, "
"end_col_offset=0)], keywords=[], lineno=1, col_offset=0, end_lineno=1, " "end_col_offset=0)], lineno=1, col_offset=0, end_lineno=1, "
"end_col_offset=0), lineno=1, col_offset=0, end_lineno=1, end_col_offset=0)], " "end_col_offset=0), lineno=1, col_offset=0, end_lineno=1, end_col_offset=0)])"
"type_ignores=[])"
) )
def test_increment_lineno(self): def test_increment_lineno(self):

View file

@ -0,0 +1,3 @@
Don't show empty fields (value ``None`` or ``[]``)
in :func:`ast.dump` by default. Add ``show_empty=False``
parameter to optionally show them.