bpo-34013: Move the Python 2 hints from the exception constructor to … · python/cpython@ecc3c8e (original) (raw)
`@@ -1475,9 +1475,6 @@ ComplexExtendsException(PyExc_Exception, AttributeError,
`
1475
1475
` * SyntaxError extends Exception
`
1476
1476
` */
`
1477
1477
``
1478
``
`-
/* Helper function to customize error message for some syntax errors */
`
1479
``
`-
static int _report_missing_parentheses(PySyntaxErrorObject *self);
`
1480
``
-
1481
1478
`static int
`
1482
1479
`SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
`
1483
1480
`{
`
`@@ -1520,18 +1517,6 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
`
1520
1517
`PyErr_SetString(PyExc_TypeError, "end_offset must be provided when end_lineno is provided");
`
1521
1518
`return -1;
`
1522
1519
` }
`
1523
``
-
1524
``
`-
/*
`
1525
``
`-
- Issue #21669: Custom error for 'print' & 'exec' as statements
`
1526
``
`-
`
1527
``
`-
- Only applies to SyntaxError instances, not to subclasses such
`
1528
``
`-
- as TabError or IndentationError (see issue #31161)
`
1529
``
`-
*/
`
1530
``
`-
if (Py_IS_TYPE(self, (PyTypeObject *)PyExc_SyntaxError) &&
`
1531
``
`-
self->text && PyUnicode_Check(self->text) &&
`
1532
``
`-
_report_missing_parentheses(self) < 0) {
`
1533
``
`-
return -1;
`
1534
``
`-
}
`
1535
1520
` }
`
1536
1521
`return 0;
`
1537
1522
`}
`
`@@ -3033,189 +3018,3 @@ _PyErr_TrySetFromCause(const char *format, ...)
`
3033
3018
`PyErr_Restore(new_exc, new_val, new_tb);
`
3034
3019
`return new_val;
`
3035
3020
`}
`
3036
``
-
3037
``
-
3038
``
`-
/* To help with migration from Python 2, SyntaxError.init applies some
`
3039
``
`-
- heuristics to try to report a more meaningful exception when print and
`
3040
``
`-
- exec are used like statements.
`
3041
``
`-
`
3042
``
`-
- The heuristics are currently expected to detect the following cases:
`
3043
``
`-
- top level statement
`
3044
``
`-
- statement in a nested suite
`
3045
``
`-
- trailing section of a one line complex statement
`
3046
``
`-
`
3047
``
`-
- They're currently known not to trigger:
`
3048
``
`-
- after a semi-colon
`
3049
``
`-
`
3050
``
`-
- The error message can be a bit odd in cases where the "arguments" are
`
3051
``
`-
- completely illegal syntactically, but that isn't worth the hassle of
`
3052
``
`-
- fixing.
`
3053
``
`-
`
3054
``
`-
- We also can't do anything about cases that are legal Python 3 syntax
`
3055
``
`-
- but mean something entirely different from what they did in Python 2
`
3056
``
`-
- (omitting the arguments entirely, printing items preceded by a unary plus
`
3057
``
`-
- or minus, using the stream redirection syntax).
`
3058
``
`-
*/
`
3059
``
-
3060
``
-
3061
``
`-
// Static helper for setting legacy print error message
`
3062
``
`-
static int
`
3063
``
`-
_set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start)
`
3064
``
`-
{
`
3065
``
`` -
// PRINT_OFFSET is to remove the print
prefix from the data.
``
3066
``
`-
const int PRINT_OFFSET = 6;
`
3067
``
`-
const int STRIP_BOTH = 2;
`
3068
``
`-
Py_ssize_t start_pos = start + PRINT_OFFSET;
`
3069
``
`-
Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text);
`
3070
``
`-
Py_UCS4 semicolon = ';';
`
3071
``
`-
Py_ssize_t end_pos = PyUnicode_FindChar(self->text, semicolon,
`
3072
``
`-
start_pos, text_len, 1);
`
3073
``
`-
if (end_pos < -1) {
`
3074
``
`-
return -1;
`
3075
``
`-
} else if (end_pos == -1) {
`
3076
``
`-
end_pos = text_len;
`
3077
``
`-
}
`
3078
``
-
3079
``
`-
PyObject *data = PyUnicode_Substring(self->text, start_pos, end_pos);
`
3080
``
`-
if (data == NULL) {
`
3081
``
`-
return -1;
`
3082
``
`-
}
`
3083
``
-
3084
``
`-
PyObject *strip_sep_obj = PyUnicode_FromString(" \t\r\n");
`
3085
``
`-
if (strip_sep_obj == NULL) {
`
3086
``
`-
Py_DECREF(data);
`
3087
``
`-
return -1;
`
3088
``
`-
}
`
3089
``
-
3090
``
`-
PyObject *new_data = _PyUnicode_XStrip(data, STRIP_BOTH, strip_sep_obj);
`
3091
``
`-
Py_DECREF(data);
`
3092
``
`-
Py_DECREF(strip_sep_obj);
`
3093
``
`-
if (new_data == NULL) {
`
3094
``
`-
return -1;
`
3095
``
`-
}
`
3096
``
`` -
// gets the modified text_len after stripping print
``
3097
``
`-
text_len = PyUnicode_GET_LENGTH(new_data);
`
3098
``
`-
const char *maybe_end_arg = "";
`
3099
``
`-
if (text_len > 0 && PyUnicode_READ_CHAR(new_data, text_len-1) == ',') {
`
3100
``
`-
maybe_end_arg = " end=" "";
`
3101
``
`-
}
`
3102
``
`-
PyObject *error_msg = PyUnicode_FromFormat(
`
3103
``
`-
"Missing parentheses in call to 'print'. Did you mean print(%U%s)?",
`
3104
``
`-
new_data, maybe_end_arg
`
3105
``
`-
);
`
3106
``
`-
Py_DECREF(new_data);
`
3107
``
`-
if (error_msg == NULL)
`
3108
``
`-
return -1;
`
3109
``
-
3110
``
`-
Py_XSETREF(self->msg, error_msg);
`
3111
``
`-
return 1;
`
3112
``
`-
}
`
3113
``
-
3114
``
`-
static int
`
3115
``
`-
_check_for_legacy_statements(PySyntaxErrorObject *self, Py_ssize_t start)
`
3116
``
`-
{
`
3117
``
`-
/* Return values:
`
3118
``
`-
- -1: an error occurred
`
3119
``
`-
- 0: nothing happened
`
3120
``
`-
- 1: the check triggered & the error message was changed
`
3121
``
`-
*/
`
3122
``
`-
static PyObject *print_prefix = NULL;
`
3123
``
`-
static PyObject *exec_prefix = NULL;
`
3124
``
`-
Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text), match;
`
3125
``
`-
int kind = PyUnicode_KIND(self->text);
`
3126
``
`-
const void *data = PyUnicode_DATA(self->text);
`
3127
``
-
3128
``
`-
/* Ignore leading whitespace */
`
3129
``
`-
while (start < text_len) {
`
3130
``
`-
Py_UCS4 ch = PyUnicode_READ(kind, data, start);
`
3131
``
`-
if (!Py_UNICODE_ISSPACE(ch))
`
3132
``
`-
break;
`
3133
``
`-
start++;
`
3134
``
`-
}
`
3135
``
`-
/* Checking against an empty or whitespace-only part of the string */
`
3136
``
`-
if (start == text_len) {
`
3137
``
`-
return 0;
`
3138
``
`-
}
`
3139
``
-
3140
``
`-
/* Check for legacy print statements */
`
3141
``
`-
if (print_prefix == NULL) {
`
3142
``
`-
print_prefix = PyUnicode_InternFromString("print ");
`
3143
``
`-
if (print_prefix == NULL) {
`
3144
``
`-
return -1;
`
3145
``
`-
}
`
3146
``
`-
}
`
3147
``
`-
match = PyUnicode_Tailmatch(self->text, print_prefix,
`
3148
``
`-
start, text_len, -1);
`
3149
``
`-
if (match == -1) {
`
3150
``
`-
return -1;
`
3151
``
`-
}
`
3152
``
`-
if (match) {
`
3153
``
`-
return _set_legacy_print_statement_msg(self, start);
`
3154
``
`-
}
`
3155
``
-
3156
``
`-
/* Check for legacy exec statements */
`
3157
``
`-
if (exec_prefix == NULL) {
`
3158
``
`-
exec_prefix = PyUnicode_InternFromString("exec ");
`
3159
``
`-
if (exec_prefix == NULL) {
`
3160
``
`-
return -1;
`
3161
``
`-
}
`
3162
``
`-
}
`
3163
``
`-
match = PyUnicode_Tailmatch(self->text, exec_prefix, start, text_len, -1);
`
3164
``
`-
if (match == -1) {
`
3165
``
`-
return -1;
`
3166
``
`-
}
`
3167
``
`-
if (match) {
`
3168
``
`-
PyObject *msg = PyUnicode_FromString("Missing parentheses in call "
`
3169
``
`-
"to 'exec'");
`
3170
``
`-
if (msg == NULL) {
`
3171
``
`-
return -1;
`
3172
``
`-
}
`
3173
``
`-
Py_XSETREF(self->msg, msg);
`
3174
``
`-
return 1;
`
3175
``
`-
}
`
3176
``
`-
/* Fall back to the default error message */
`
3177
``
`-
return 0;
`
3178
``
`-
}
`
3179
``
-
3180
``
`-
static int
`
3181
``
`-
_report_missing_parentheses(PySyntaxErrorObject *self)
`
3182
``
`-
{
`
3183
``
`-
Py_UCS4 left_paren = 40;
`
3184
``
`-
Py_ssize_t left_paren_index;
`
3185
``
`-
Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text);
`
3186
``
`-
int legacy_check_result = 0;
`
3187
``
-
3188
``
`-
/* Skip entirely if there is an opening parenthesis */
`
3189
``
`-
left_paren_index = PyUnicode_FindChar(self->text, left_paren,
`
3190
``
`-
0, text_len, 1);
`
3191
``
`-
if (left_paren_index < -1) {
`
3192
``
`-
return -1;
`
3193
``
`-
}
`
3194
``
`-
if (left_paren_index != -1) {
`
3195
``
`-
/* Use default error message for any line with an opening paren */
`
3196
``
`-
return 0;
`
3197
``
`-
}
`
3198
``
`-
/* Handle the simple statement case */
`
3199
``
`-
legacy_check_result = _check_for_legacy_statements(self, 0);
`
3200
``
`-
if (legacy_check_result < 0) {
`
3201
``
`-
return -1;
`
3202
``
-
3203
``
`-
}
`
3204
``
`-
if (legacy_check_result == 0) {
`
3205
``
`-
/* Handle the one-line complex statement case */
`
3206
``
`-
Py_UCS4 colon = 58;
`
3207
``
`-
Py_ssize_t colon_index;
`
3208
``
`-
colon_index = PyUnicode_FindChar(self->text, colon,
`
3209
``
`-
0, text_len, 1);
`
3210
``
`-
if (colon_index < -1) {
`
3211
``
`-
return -1;
`
3212
``
`-
}
`
3213
``
`-
if (colon_index >= 0 && colon_index < text_len) {
`
3214
``
`-
/* Check again, starting from just after the colon */
`
3215
``
`-
if (_check_for_legacy_statements(self, colon_index+1) < 0) {
`
3216
``
`-
return -1;
`
3217
``
`-
}
`
3218
``
`-
}
`
3219
``
`-
}
`
3220
``
`-
return 0;
`
3221
``
`-
}
`