mirror of
https://github.com/python/cpython.git
synced 2024-11-29 04:44:13 +08:00
bpo-30597: Show expected input in custom 'print' error message. (#2009)
This commit is contained in:
parent
90e01e50ef
commit
3a7f03584a
@ -128,5 +128,33 @@ class TestPrint(unittest.TestCase):
|
||||
raise RuntimeError
|
||||
self.assertRaises(RuntimeError, print, 1, file=noflush(), flush=True)
|
||||
|
||||
|
||||
class TestPy2MigrationHint(unittest.TestCase):
|
||||
"""Test that correct hint is produced analogous to Python3 syntax,
|
||||
if print statement is executed as in Python 2.
|
||||
"""
|
||||
|
||||
def test_normal_string(self):
|
||||
python2_print_str = 'print "Hello World"'
|
||||
with self.assertRaises(SyntaxError) as context:
|
||||
exec(python2_print_str)
|
||||
|
||||
self.assertIn('print("Hello World")', str(context.exception))
|
||||
|
||||
def test_string_with_soft_space(self):
|
||||
python2_print_str = 'print "Hello World",'
|
||||
with self.assertRaises(SyntaxError) as context:
|
||||
exec(python2_print_str)
|
||||
|
||||
self.assertIn('print("Hello World", end=" ")', str(context.exception))
|
||||
|
||||
def test_string_with_excessive_whitespace(self):
|
||||
python2_print_str = 'print "Hello World", '
|
||||
with self.assertRaises(SyntaxError) as context:
|
||||
exec(python2_print_str)
|
||||
|
||||
self.assertIn('print("Hello World", end=" ")', str(context.exception))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1?
|
||||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- bpo-30597: ``print`` now shows expected input in custom error message when
|
||||
used as a Python 2 statement. Patch by Sanyam Khurana.
|
||||
|
||||
- bpo-30682: Removed a too-strict assertion that failed for certain f-strings,
|
||||
such as eval("f'\\\n'") and eval("f'\\\r'").
|
||||
|
||||
|
@ -2862,6 +2862,49 @@ _PyErr_TrySetFromCause(const char *format, ...)
|
||||
* or minus, using the stream redirection syntax).
|
||||
*/
|
||||
|
||||
|
||||
// Static helper for setting legacy print error message
|
||||
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.
|
||||
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);
|
||||
|
||||
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);
|
||||
const char *maybe_end_arg = "";
|
||||
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)?",
|
||||
new_data, maybe_end_arg
|
||||
);
|
||||
Py_DECREF(new_data);
|
||||
if (error_msg == NULL)
|
||||
return -1;
|
||||
|
||||
Py_XSETREF(self->msg, error_msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
_check_for_legacy_statements(PySyntaxErrorObject *self, Py_ssize_t start)
|
||||
{
|
||||
@ -2897,9 +2940,8 @@ _check_for_legacy_statements(PySyntaxErrorObject *self, Py_ssize_t start)
|
||||
}
|
||||
if (PyUnicode_Tailmatch(self->text, print_prefix,
|
||||
start, text_len, -1)) {
|
||||
Py_XSETREF(self->msg,
|
||||
PyUnicode_FromString("Missing parentheses in call to 'print'"));
|
||||
return 1;
|
||||
|
||||
return _set_legacy_print_statement_msg(self, start);
|
||||
}
|
||||
|
||||
/* Check for legacy exec statements */
|
||||
|
Loading…
Reference in New Issue
Block a user