Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Lib/test/test_print.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,23 @@ def test_string_with_leading_whitespace(self):

self.assertIn('print("Hello World")', str(context.exception))

# bpo-32685: Suggestions for print statement should be proper when
# it is in the same line as the header of a compound statement
# and/or followed by a semicolon
def test_string_with_semicolon(self):
python2_print_str = 'print p;'
with self.assertRaises(SyntaxError) as context:
exec(python2_print_str)

self.assertIn('print(p)', str(context.exception))

def test_string_in_loop_on_same_line(self):
python2_print_str = 'for i in s: print i'
with self.assertRaises(SyntaxError) as context:
exec(python2_print_str)

self.assertIn('print(i)', 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:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Improve suggestion when the Python 2 form of print statement is either
present on the same line as the header of a compound statement or else
terminated by a semi-colon instead of a newline. Patch by Nitish Chandra.
33 changes: 19 additions & 14 deletions Objects/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -2859,26 +2859,31 @@ _PyErr_TrySetFromCause(const char *format, ...)
static int
_set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start)
{
PyObject *strip_sep_obj = PyUnicode_FromString(" \t\r\n");
if (strip_sep_obj == NULL)
return -1;

// PRINT_OFFSET is to remove `print ` word from the data.
// PRINT_OFFSET is to remove the `print ` prefix from the data.
const int PRINT_OFFSET = 6;
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 start_pos = start + PRINT_OFFSET;
Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text);
Py_UCS4 semicolon = ';';
Py_ssize_t end_pos = PyUnicode_FindChar(self->text, semicolon,
start_pos, text_len, 1);
if (end_pos < -1) {
return -1;
} else if (end_pos == -1) {
end_pos = text_len;
}
Py_ssize_t text_len = PyUnicode_GET_LENGTH(initial_data);
PyObject *data = PyUnicode_Substring(initial_data, PRINT_OFFSET, text_len);
Py_DECREF(initial_data);

PyObject *data = PyUnicode_Substring(self->text, start_pos, end_pos);
if (data == NULL) {
Py_DECREF(strip_sep_obj);
return -1;
}

PyObject *strip_sep_obj = PyUnicode_FromString(" \t\r\n");
if (strip_sep_obj == NULL) {
Py_DECREF(data);
return -1;
}

PyObject *new_data = _PyUnicode_XStrip(data, STRIP_BOTH, strip_sep_obj);
Py_DECREF(data);
Py_DECREF(strip_sep_obj);
Expand Down