From 99c26e872c6b5f96a549fc48202fa1f82e836340 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Sun, 3 Dec 2017 22:30:08 +0530 Subject: [PATCH 1/7] bpo-32028: Fix custom print suggestion having leading whitespace in print statement --- Lib/test/test_print.py | 9 +++++++++ .../2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst | 2 ++ Objects/exceptions.c | 5 ++++- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index e6434feaf5eec6..ad9786f3d856d0 100644 --- a/Lib/test/test_print.py +++ b/Lib/test/test_print.py @@ -156,6 +156,15 @@ def test_string_with_excessive_whitespace(self): self.assertIn('print("Hello World", end=" ")', str(context.exception)) + def test_string_with_leading_whitespace(self): + python2_print_str = '''if 1: + print "Hello World" + ''' + with self.assertRaises(SyntaxError) as context: + exec(python2_print_str) + + self.assertIn('print("Hello World")', str(context.exception)) + def test_stream_redirection_hint_for_py2_migration(self): # Test correct hint produced for Py2 redirection syntax with self.assertRaises(TypeError) as context: diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst new file mode 100644 index 00000000000000..4501017260ff39 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst @@ -0,0 +1,2 @@ +Fix py2 to py3 custom print suggestion message having leading whitespaces in +print statement. Patch by Sanyam Khurana. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 4901eb1cc3c560..914d5eef7b172c 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2847,7 +2847,10 @@ _set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start) // PRINT_OFFSET is to remove `print ` word from the data. const int PRINT_OFFSET = 6; Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text); - PyObject *data = PyUnicode_Substring(self->text, PRINT_OFFSET, text_len); + // Issue 32028: Handle case when whitespace is used with print call + PyObject *initial_data = _PyUnicode_XStrip(self->text, 2, strip_sep_obj); + PyObject *data = PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len); + Py_DECREF(initial_data); if (data == NULL) { Py_DECREF(strip_sep_obj); From 44c28b2070488c4c66cc122901e0ebfd89e1c8c6 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 4 Dec 2017 19:06:02 +0530 Subject: [PATCH 2/7] Address Nick's review --- Lib/test/test_print.py | 2 +- Objects/exceptions.c | 21 ++++++++------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index ad9786f3d856d0..7bc23cf9fc63aa 100644 --- a/Lib/test/test_print.py +++ b/Lib/test/test_print.py @@ -158,7 +158,7 @@ def test_string_with_excessive_whitespace(self): def test_string_with_leading_whitespace(self): python2_print_str = '''if 1: - print "Hello World" + print "Hello World" ''' with self.assertRaises(SyntaxError) as context: exec(python2_print_str) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 914d5eef7b172c..ef76130dca7106 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2846,34 +2846,29 @@ _set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start) // PRINT_OFFSET is to remove `print ` word from the data. const int PRINT_OFFSET = 6; - Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text); + const int STRIP_BOTH = 2; // Issue 32028: Handle case when whitespace is used with print call - PyObject *initial_data = _PyUnicode_XStrip(self->text, 2, strip_sep_obj); + PyObject *initial_data = _PyUnicode_XStrip(self->text, STRIP_BOTH, strip_sep_obj); + Py_ssize_t text_len = PyUnicode_GET_LENGTH(initial_data); PyObject *data = PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len); Py_DECREF(initial_data); + Py_DECREF(strip_sep_obj); if (data == NULL) { - Py_DECREF(strip_sep_obj); return -1; } - PyObject *new_data = _PyUnicode_XStrip(data, 2, strip_sep_obj); - Py_DECREF(data); - Py_DECREF(strip_sep_obj); - if (new_data == NULL) { - return -1; - } // gets the modified text_len after stripping `print ` - text_len = PyUnicode_GET_LENGTH(new_data); + text_len = PyUnicode_GET_LENGTH(data); const char *maybe_end_arg = ""; - if (text_len > 0 && PyUnicode_READ_CHAR(new_data, text_len-1) == ',') { + if (text_len > 0 && PyUnicode_READ_CHAR(data, text_len-1) == ',') { maybe_end_arg = " end=\" \""; } PyObject *error_msg = PyUnicode_FromFormat( "Missing parentheses in call to 'print'. Did you mean print(%U%s)?", - new_data, maybe_end_arg + data, maybe_end_arg ); - Py_DECREF(new_data); + Py_DECREF(data); if (error_msg == NULL) return -1; From 74ed54e418006284f03d4a0440ee9fb1bd2def09 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 4 Dec 2017 19:19:14 +0530 Subject: [PATCH 3/7] Use XStrip again to modify --- Objects/exceptions.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index ef76130dca7106..60d6950ff45d29 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2850,7 +2850,10 @@ _set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start) // Issue 32028: Handle case when whitespace is used with print call PyObject *initial_data = _PyUnicode_XStrip(self->text, STRIP_BOTH, strip_sep_obj); Py_ssize_t text_len = PyUnicode_GET_LENGTH(initial_data); - PyObject *data = PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len); + PyObject *data = _PyUnicode_XStrip( \ + PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len), \ + STRIP_BOTH, strip_sep_obj); + Py_DECREF(initial_data); Py_DECREF(strip_sep_obj); From 2c330a5721320a2f0e89f477831c59f9e7fe76dc Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 4 Dec 2017 21:25:13 +0530 Subject: [PATCH 4/7] Address Serhiy's review --- Objects/exceptions.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 60d6950ff45d29..1167d423fc7678 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2849,29 +2849,40 @@ _set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start) const int STRIP_BOTH = 2; // Issue 32028: Handle case when whitespace is used with print call PyObject *initial_data = _PyUnicode_XStrip(self->text, STRIP_BOTH, strip_sep_obj); + + if (initial_data == NULL) { + Py_DECREF(strip_sep_obj); + return -1; + } + Py_ssize_t text_len = PyUnicode_GET_LENGTH(initial_data); - PyObject *data = _PyUnicode_XStrip( \ - PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len), \ - STRIP_BOTH, strip_sep_obj); + PyObject *data = PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len); Py_DECREF(initial_data); - Py_DECREF(strip_sep_obj); if (data == NULL) { + Py_DECREF(strip_sep_obj); + return -1; + } + + PyObject *new_data = _PyUnicode_XStrip(data, STRIP_BOTH, strip_sep_obj); + Py_DECREF(strip_sep_obj); + + if (new_data == NULL) { return -1; } // gets the modified text_len after stripping `print ` - text_len = PyUnicode_GET_LENGTH(data); + text_len = PyUnicode_GET_LENGTH(new_data); const char *maybe_end_arg = ""; - if (text_len > 0 && PyUnicode_READ_CHAR(data, text_len-1) == ',') { + if (text_len > 0 && PyUnicode_READ_CHAR(new_data, text_len-1) == ',') { maybe_end_arg = " end=\" \""; } PyObject *error_msg = PyUnicode_FromFormat( "Missing parentheses in call to 'print'. Did you mean print(%U%s)?", - data, maybe_end_arg + new_data, maybe_end_arg ); - Py_DECREF(data); + Py_DECREF(new_data); if (error_msg == NULL) return -1; From 3e5b704851360053f2e8967916147e26abf4b5d6 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 4 Dec 2017 21:27:22 +0530 Subject: [PATCH 5/7] Handle memory leak for --- Objects/exceptions.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 1167d423fc7678..ee282844f57093 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2866,6 +2866,7 @@ _set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start) } PyObject *new_data = _PyUnicode_XStrip(data, STRIP_BOTH, strip_sep_obj); + Py_DECREF(data); Py_DECREF(strip_sep_obj); if (new_data == NULL) { From aaa850b641f4fe2bae7e2c596d1c99edf87ea0c1 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 4 Dec 2017 23:14:10 +0530 Subject: [PATCH 6/7] Remove redundant lines --- Objects/exceptions.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index ee282844f57093..d59abd1a7f4119 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2849,30 +2849,23 @@ _set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start) const int STRIP_BOTH = 2; // Issue 32028: Handle case when whitespace is used with print call PyObject *initial_data = _PyUnicode_XStrip(self->text, STRIP_BOTH, strip_sep_obj); - if (initial_data == NULL) { Py_DECREF(strip_sep_obj); return -1; } - Py_ssize_t text_len = PyUnicode_GET_LENGTH(initial_data); - PyObject *data = PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len); Py_DECREF(initial_data); - if (data == NULL) { Py_DECREF(strip_sep_obj); return -1; } - PyObject *new_data = _PyUnicode_XStrip(data, STRIP_BOTH, strip_sep_obj); Py_DECREF(data); Py_DECREF(strip_sep_obj); - if (new_data == NULL) { return -1; } - // gets the modified text_len after stripping `print ` text_len = PyUnicode_GET_LENGTH(new_data); const char *maybe_end_arg = ""; From 2abeecd49145dd5ad5a744fddcd3e03507602771 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Tue, 5 Dec 2017 12:48:32 +1000 Subject: [PATCH 7/7] Adjust wording of NEWS entry --- .../2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst index 4501017260ff39..8e2b2e1b35038b 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-03-22-29-13.bpo-32028.KC2w4Q.rst @@ -1,2 +1,3 @@ -Fix py2 to py3 custom print suggestion message having leading whitespaces in -print statement. Patch by Sanyam Khurana. +Leading whitespace is now correctly ignored when generating suggestions +for converting Py2 print statements to Py3 builtin print function calls. +Patch by Sanyam Khurana.