Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
850573b8
Commit
850573b8
authored
Sep 09, 2019
by
Serhiy Storchaka
Committed by
GitHub
Sep 09, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-37995: Add an option to ast.dump() to produce a multiline output. (GH-15631)
parent
92709a26
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
118 additions
and
12 deletions
+118
-12
Doc/library/ast.rst
Doc/library/ast.rst
+12
-1
Doc/whatsnew/3.9.rst
Doc/whatsnew/3.9.rst
+8
-0
Lib/ast.py
Lib/ast.py
+34
-11
Lib/test/test_ast.py
Lib/test/test_ast.py
+62
-0
Misc/NEWS.d/next/Library/2019-08-31-13-36-09.bpo-37995.rS8HzT.rst
...S.d/next/Library/2019-08-31-13-36-09.bpo-37995.rS8HzT.rst
+2
-0
No files found.
Doc/library/ast.rst
View file @
850573b8
...
...
@@ -319,7 +319,7 @@ and classes for traversing abstract syntax trees:
node = YourTransformer().visit(node)
.. function:: dump(node, annotate_fields=True, include_attributes=False)
.. function:: dump(node, annotate_fields=True, include_attributes=False
, *, indent=None
)
Return a formatted dump of the tree in *node*. This is mainly useful for
debugging purposes. If *annotate_fields* is true (by default),
...
...
@@ -329,6 +329,17 @@ and classes for traversing abstract syntax trees:
numbers and column offsets are not dumped by default. If this is wanted,
*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 level. An indent level
of 0, negative, or ``""`` will only insert newlines. ``None`` (the default)
selects the single line representation. Using a positive integer indent
indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
that string is used to indent each level.
.. versionchanged:: 3.9
Added the *indent* option.
.. seealso::
`Green Tree Snakes <https://greentreesnakes.readthedocs.io/>`_, an external documentation resource, has good
...
...
Doc/whatsnew/3.9.rst
View file @
850573b8
...
...
@@ -109,6 +109,14 @@ New Modules
Improved Modules
================
ast
---
Added the *indent* option to :func:`~ast.dump` which allows it to produce a
multiline indented output.
(Contributed by Serhiy Storchaka in :issue:`37995`.)
threading
---------
...
...
Lib/ast.py
View file @
850573b8
...
...
@@ -96,7 +96,7 @@ def literal_eval(node_or_string):
return
_convert
(
node_or_string
)
def
dump
(
node
,
annotate_fields
=
True
,
include_attributes
=
False
):
def
dump
(
node
,
annotate_fields
=
True
,
include_attributes
=
False
,
*
,
indent
=
None
):
"""
Return a formatted dump of the tree in node. This is mainly useful for
debugging purposes. If annotate_fields is true (by default),
...
...
@@ -104,11 +104,21 @@ def dump(node, annotate_fields=True, include_attributes=False):
If annotate_fields is false, the result string will be more compact by
omitting unambiguous field names. Attributes such as line
numbers and column offsets are not dumped by default. If this is wanted,
include_attributes can be set to true.
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
level. None (the default) selects the single line representation.
"""
def
_format
(
node
):
def
_format
(
node
,
level
=
0
):
if
indent
is
not
None
:
level
+=
1
prefix
=
'
\
n
'
+
indent
*
level
sep
=
',
\
n
'
+
indent
*
level
else
:
prefix
=
''
sep
=
', '
if
isinstance
(
node
,
AST
):
args
=
[]
allsimple
=
True
keywords
=
annotate_fields
for
field
in
node
.
_fields
:
try
:
...
...
@@ -116,23 +126,36 @@ def dump(node, annotate_fields=True, include_attributes=False):
except
AttributeError
:
keywords
=
True
else
:
value
,
simple
=
_format
(
value
,
level
)
allsimple
=
allsimple
and
simple
if
keywords
:
args
.
append
(
'%s=%s'
%
(
field
,
_format
(
value
)
))
args
.
append
(
'%s=%s'
%
(
field
,
value
))
else
:
args
.
append
(
_format
(
value
)
)
args
.
append
(
value
)
if
include_attributes
and
node
.
_attributes
:
for
a
in
node
.
_attributes
:
for
a
ttr
in
node
.
_attributes
:
try
:
args
.
append
(
'%s=%s'
%
(
a
,
_format
(
getattr
(
node
,
a
)))
)
value
=
getattr
(
node
,
attr
)
except
AttributeError
:
pass
return
'%s(%s)'
%
(
node
.
__class__
.
__name__
,
', '
.
join
(
args
))
else
:
value
,
simple
=
_format
(
value
,
level
)
allsimple
=
allsimple
and
simple
args
.
append
(
'%s=%s'
%
(
attr
,
value
))
if
allsimple
and
len
(
args
)
<=
3
:
return
'%s(%s)'
%
(
node
.
__class__
.
__name__
,
', '
.
join
(
args
)),
not
args
return
'%s(%s%s)'
%
(
node
.
__class__
.
__name__
,
prefix
,
sep
.
join
(
args
)),
False
elif
isinstance
(
node
,
list
):
return
'[%s]'
%
', '
.
join
(
_format
(
x
)
for
x
in
node
)
return
repr
(
node
)
if
not
node
:
return
'[]'
,
True
return
'[%s%s]'
%
(
prefix
,
sep
.
join
(
_format
(
x
,
level
)[
0
]
for
x
in
node
)),
False
return
repr
(
node
),
True
if
not
isinstance
(
node
,
AST
):
raise
TypeError
(
'expected AST, got %r'
%
node
.
__class__
.
__name__
)
return
_format
(
node
)
if
indent
is
not
None
and
not
isinstance
(
indent
,
str
):
indent
=
' '
*
indent
return
_format
(
node
)[
0
]
def
copy_location
(
new_node
,
old_node
):
...
...
Lib/test/test_ast.py
View file @
850573b8
...
...
@@ -645,6 +645,68 @@ class ASTHelpers_Test(unittest.TestCase):
"lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)], type_ignores=[])"
)
def
test_dump_indent
(
self
):
node
=
ast
.
parse
(
'spam(eggs, "and cheese")'
)
self
.
assertEqual
(
ast
.
dump
(
node
,
indent
=
3
),
"""
\
Module(
body=[
Expr(
value=Call(
func=Name(id='spam', ctx=Load()),
args=[
Name(id='eggs', ctx=Load()),
Constant(value='and cheese', kind=None)],
keywords=[]))],
type_ignores=[])"""
)
self
.
assertEqual
(
ast
.
dump
(
node
,
annotate_fields
=
False
,
indent
=
'
\
t
'
),
"""
\
Module(
\
t
[
\
t
\
t
Expr(
\
t
\
t
\
t
Call(
\
t
\
t
\
t
\
t
Name('spam', Load()),
\
t
\
t
\
t
\
t
[
\
t
\
t
\
t
\
t
\
t
Name('eggs', Load()),
\
t
\
t
\
t
\
t
\
t
Constant('and cheese', None)],
\
t
\
t
\
t
\
t
[]))],
\
t
[])"""
)
self
.
assertEqual
(
ast
.
dump
(
node
,
include_attributes
=
True
,
indent
=
3
),
"""
\
Module(
body=[
Expr(
value=Call(
func=Name(
id='spam',
ctx=Load(),
lineno=1,
col_offset=0,
end_lineno=1,
end_col_offset=4),
args=[
Name(
id='eggs',
ctx=Load(),
lineno=1,
col_offset=5,
end_lineno=1,
end_col_offset=9),
Constant(
value='and cheese',
kind=None,
lineno=1,
col_offset=11,
end_lineno=1,
end_col_offset=23)],
keywords=[],
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=[])"""
)
def
test_dump_incomplete
(
self
):
node
=
ast
.
Raise
(
lineno
=
3
,
col_offset
=
4
)
self
.
assertEqual
(
ast
.
dump
(
node
),
...
...
Misc/NEWS.d/next/Library/2019-08-31-13-36-09.bpo-37995.rS8HzT.rst
0 → 100644
View file @
850573b8
Added the *indent* option to :func:`ast.dump` which allows it to produce a
multiline indented output.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment