[Python-checkins] bpo-38870: correctly escape unprintable characters on ast.unparse (GH-20166)
CyberSaxosTiGER
webhook-mailer at python.org
Mon May 18 14:41:48 EDT 2020
https://github.com/python/cpython/commit/d71a6492dbd5434dfa6a0ad95e3ad98aa690887a
commit: d71a6492dbd5434dfa6a0ad95e3ad98aa690887a
branch: master
author: CyberSaxosTiGER <cybersaxostiger at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-05-18T19:41:35+01:00
summary:
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 <Pablogsal at gmail.com>
Co-authored-by: Batuhan Taskaya <isidentical at gmail.com>
files:
M Lib/ast.py
M Lib/test/test_unparse.py
diff --git a/Lib/ast.py b/Lib/ast.py
index 0d3b19d922368..2edb7171e9671 100644
--- a/Lib/ast.py
+++ b/Lib/ast.py
@@ -1090,6 +1090,15 @@ def visit_Name(self, node):
self.write(node.id)
def _write_docstring(self, node):
+ def esc_char(c):
+ if c in ("\n", "\t"):
+ # In the AST form, we don't know the author's intentation
+ # about how this should be displayed. We'll only escape
+ # \n and \t, because they are more likely to be unescaped
+ # in the source
+ return c
+ return c.encode('unicode_escape').decode('ascii')
+
self.fill()
if node.kind == "u":
self.write("u")
@@ -1097,11 +1106,10 @@ def _write_docstring(self, node):
value = node.value
if value:
# Preserve quotes in the docstring by escaping them
- value = value.replace("\\", "\\\\")
- value = value.replace('"""', '""\"')
- value = value.replace("\r", "\\r")
+ value = "".join(map(esc_char, value))
if value[-1] == '"':
value = value.replace('"', '\\"', -1)
+ value = value.replace('"""', '""\\"')
self.write(f'"""{value}"""')
diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py
index 67dcb1dae79ff..6d828721b7740 100644
--- a/Lib/test/test_unparse.py
+++ b/Lib/test/test_unparse.py
@@ -324,7 +324,11 @@ def test_docstrings(self):
'\\t',
'\n',
'\\n',
- '\r\\r\t\\t\n\\n'
+ '\r\\r\t\\t\n\\n',
+ '""">>> content = \"\"\"blabla\"\"\" <<<"""',
+ r'foo\n\x00',
+ '🐍⛎𩸽üéş^\X\BB\N{LONG RIGHTWARDS SQUIGGLE ARROW}'
+
)
for docstring in docstrings:
# check as Module docstrings for easy testing
More information about the Python-checkins
mailing list