bpo-30597: Show expected input in custom 'print' error message. (#2009) · python/cpython@3a7f035
@@ -2862,6 +2862,49 @@ _PyErr_TrySetFromCause(const char *format, ...)
28622862 * or minus, using the stream redirection syntax).
28632863 */
286428642865+2866+// Static helper for setting legacy print error message
2867+static int
2868+_set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start)
2869+{
2870+PyObject *strip_sep_obj = PyUnicode_FromString(" \t\r\n");
2871+if (strip_sep_obj == NULL)
2872+return -1;
2873+2874+// PRINT_OFFSET is to remove `print ` word from the data.
2875+const int PRINT_OFFSET = 6;
2876+Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text);
2877+PyObject *data = PyUnicode_Substring(self->text, PRINT_OFFSET, text_len);
2878+2879+if (data == NULL) {
2880+Py_DECREF(strip_sep_obj);
2881+return -1;
2882+ }
2883+PyObject *new_data = _PyUnicode_XStrip(data, 2, strip_sep_obj);
2884+Py_DECREF(data);
2885+Py_DECREF(strip_sep_obj);
2886+2887+if (new_data == NULL) {
2888+return -1;
2889+ }
2890+// gets the modified text_len after stripping `print `
2891+text_len = PyUnicode_GET_LENGTH(new_data);
2892+const char *maybe_end_arg = "";
2893+if (text_len > 0 && PyUnicode_READ_CHAR(new_data, text_len-1) == ',') {
2894+maybe_end_arg = " end=\" \"";
2895+ }
2896+PyObject *error_msg = PyUnicode_FromFormat(
2897+"Missing parentheses in call to 'print'. Did you mean print(%U%s)?",
2898+new_data, maybe_end_arg
2899+ );
2900+Py_DECREF(new_data);
2901+if (error_msg == NULL)
2902+return -1;
2903+2904+Py_XSETREF(self->msg, error_msg);
2905+return 1;
2906+}
2907+28652908static int
28662909_check_for_legacy_statements(PySyntaxErrorObject *self, Py_ssize_t start)
28672910{
@@ -2897,9 +2940,8 @@ _check_for_legacy_statements(PySyntaxErrorObject *self, Py_ssize_t start)
28972940 }
28982941if (PyUnicode_Tailmatch(self->text, print_prefix,
28992942start, text_len, -1)) {
2900-Py_XSETREF(self->msg,
2901-PyUnicode_FromString("Missing parentheses in call to 'print'"));
2902-return 1;
2943+2944+return _set_legacy_print_statement_msg(self, start);
29032945 }
2904294629052947/* Check for legacy exec statements */