Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d71a649

Browse files
i64pablogsalisidentical
authored
bpo-38870: correctly escape unprintable characters on ast.unparse (GH-20166)
Unprintable characters such as `\x00` weren't correctly roundtripped due to not using default string repr when generating docstrings. This patch correctly encodes all unprintable characters (except `\n` and `\t`, which are commonly used for formatting, and found unescaped). Co-authored-by: Pablo Galindo <[email protected]> Co-authored-by: Batuhan Taskaya <[email protected]>
1 parent dc31800 commit d71a649

2 files changed

Lines changed: 16 additions & 4 deletions

File tree

Lib/ast.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,18 +1090,26 @@ def visit_Name(self, node):
10901090
self.write(node.id)
10911091

10921092
def _write_docstring(self, node):
1093+
def esc_char(c):
1094+
if c in ("\n", "\t"):
1095+
# In the AST form, we don't know the author's intentation
1096+
# about how this should be displayed. We'll only escape
1097+
# \n and \t, because they are more likely to be unescaped
1098+
# in the source
1099+
return c
1100+
return c.encode('unicode_escape').decode('ascii')
1101+
10931102
self.fill()
10941103
if node.kind == "u":
10951104
self.write("u")
10961105

10971106
value = node.value
10981107
if value:
10991108
# Preserve quotes in the docstring by escaping them
1100-
value = value.replace("\\", "\\\\")
1101-
value = value.replace('"""', '""\"')
1102-
value = value.replace("\r", "\\r")
1109+
value = "".join(map(esc_char, value))
11031110
if value[-1] == '"':
11041111
value = value.replace('"', '\\"', -1)
1112+
value = value.replace('"""', '""\\"')
11051113

11061114
self.write(f'"""{value}"""')
11071115

Lib/test/test_unparse.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,11 @@ def test_docstrings(self):
324324
'\\t',
325325
'\n',
326326
'\\n',
327-
'\r\\r\t\\t\n\\n'
327+
'\r\\r\t\\t\n\\n',
328+
'""">>> content = \"\"\"blabla\"\"\" <<<"""',
329+
r'foo\n\x00',
330+
'🐍⛎𩸽üéş^\X\BB\N{LONG RIGHTWARDS SQUIGGLE ARROW}'
331+
328332
)
329333
for docstring in docstrings:
330334
# check as Module docstrings for easy testing

0 commit comments

Comments
 (0)