@@ -1475,9 +1475,6 @@ ComplexExtendsException(PyExc_Exception, AttributeError,
14751475 * SyntaxError extends Exception
14761476 */
14771477
1478- /* Helper function to customize error message for some syntax errors */
1479- static int _report_missing_parentheses (PySyntaxErrorObject * self );
1480-
14811478static int
14821479SyntaxError_init (PySyntaxErrorObject * self , PyObject * args , PyObject * kwds )
14831480{
@@ -1520,18 +1517,6 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
15201517 PyErr_SetString (PyExc_TypeError , "end_offset must be provided when end_lineno is provided" );
15211518 return -1 ;
15221519 }
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- }
15351520 }
15361521 return 0 ;
15371522}
@@ -3052,189 +3037,3 @@ _PyErr_TrySetFromCause(const char *format, ...)
30523037 PyErr_Restore (new_exc , new_val , new_tb );
30533038 return new_val ;
30543039}
3055-
3056-
3057- /* To help with migration from Python 2, SyntaxError.__init__ applies some
3058- * heuristics to try to report a more meaningful exception when print and
3059- * exec are used like statements.
3060- *
3061- * The heuristics are currently expected to detect the following cases:
3062- * - top level statement
3063- * - statement in a nested suite
3064- * - trailing section of a one line complex statement
3065- *
3066- * They're currently known not to trigger:
3067- * - after a semi-colon
3068- *
3069- * The error message can be a bit odd in cases where the "arguments" are
3070- * completely illegal syntactically, but that isn't worth the hassle of
3071- * fixing.
3072- *
3073- * We also can't do anything about cases that are legal Python 3 syntax
3074- * but mean something entirely different from what they did in Python 2
3075- * (omitting the arguments entirely, printing items preceded by a unary plus
3076- * or minus, using the stream redirection syntax).
3077- */
3078-
3079-
3080- // Static helper for setting legacy print error message
3081- static int
3082- _set_legacy_print_statement_msg (PySyntaxErrorObject * self , Py_ssize_t start )
3083- {
3084- // PRINT_OFFSET is to remove the `print ` prefix from the data.
3085- const int PRINT_OFFSET = 6 ;
3086- const int STRIP_BOTH = 2 ;
3087- Py_ssize_t start_pos = start + PRINT_OFFSET ;
3088- Py_ssize_t text_len = PyUnicode_GET_LENGTH (self -> text );
3089- Py_UCS4 semicolon = ';' ;
3090- Py_ssize_t end_pos = PyUnicode_FindChar (self -> text , semicolon ,
3091- start_pos , text_len , 1 );
3092- if (end_pos < -1 ) {
3093- return -1 ;
3094- } else if (end_pos == -1 ) {
3095- end_pos = text_len ;
3096- }
3097-
3098- PyObject * data = PyUnicode_Substring (self -> text , start_pos , end_pos );
3099- if (data == NULL ) {
3100- return -1 ;
3101- }
3102-
3103- PyObject * strip_sep_obj = PyUnicode_FromString (" \t\r\n" );
3104- if (strip_sep_obj == NULL ) {
3105- Py_DECREF (data );
3106- return -1 ;
3107- }
3108-
3109- PyObject * new_data = _PyUnicode_XStrip (data , STRIP_BOTH , strip_sep_obj );
3110- Py_DECREF (data );
3111- Py_DECREF (strip_sep_obj );
3112- if (new_data == NULL ) {
3113- return -1 ;
3114- }
3115- // gets the modified text_len after stripping `print `
3116- text_len = PyUnicode_GET_LENGTH (new_data );
3117- const char * maybe_end_arg = "" ;
3118- if (text_len > 0 && PyUnicode_READ_CHAR (new_data , text_len - 1 ) == ',' ) {
3119- maybe_end_arg = " end=\" \"" ;
3120- }
3121- PyObject * error_msg = PyUnicode_FromFormat (
3122- "Missing parentheses in call to 'print'. Did you mean print(%U%s)?" ,
3123- new_data , maybe_end_arg
3124- );
3125- Py_DECREF (new_data );
3126- if (error_msg == NULL )
3127- return -1 ;
3128-
3129- Py_XSETREF (self -> msg , error_msg );
3130- return 1 ;
3131- }
3132-
3133- static int
3134- _check_for_legacy_statements (PySyntaxErrorObject * self , Py_ssize_t start )
3135- {
3136- /* Return values:
3137- * -1: an error occurred
3138- * 0: nothing happened
3139- * 1: the check triggered & the error message was changed
3140- */
3141- static PyObject * print_prefix = NULL ;
3142- static PyObject * exec_prefix = NULL ;
3143- Py_ssize_t text_len = PyUnicode_GET_LENGTH (self -> text ), match ;
3144- int kind = PyUnicode_KIND (self -> text );
3145- const void * data = PyUnicode_DATA (self -> text );
3146-
3147- /* Ignore leading whitespace */
3148- while (start < text_len ) {
3149- Py_UCS4 ch = PyUnicode_READ (kind , data , start );
3150- if (!Py_UNICODE_ISSPACE (ch ))
3151- break ;
3152- start ++ ;
3153- }
3154- /* Checking against an empty or whitespace-only part of the string */
3155- if (start == text_len ) {
3156- return 0 ;
3157- }
3158-
3159- /* Check for legacy print statements */
3160- if (print_prefix == NULL ) {
3161- print_prefix = PyUnicode_InternFromString ("print " );
3162- if (print_prefix == NULL ) {
3163- return -1 ;
3164- }
3165- }
3166- match = PyUnicode_Tailmatch (self -> text , print_prefix ,
3167- start , text_len , -1 );
3168- if (match == -1 ) {
3169- return -1 ;
3170- }
3171- if (match ) {
3172- return _set_legacy_print_statement_msg (self , start );
3173- }
3174-
3175- /* Check for legacy exec statements */
3176- if (exec_prefix == NULL ) {
3177- exec_prefix = PyUnicode_InternFromString ("exec " );
3178- if (exec_prefix == NULL ) {
3179- return -1 ;
3180- }
3181- }
3182- match = PyUnicode_Tailmatch (self -> text , exec_prefix , start , text_len , -1 );
3183- if (match == -1 ) {
3184- return -1 ;
3185- }
3186- if (match ) {
3187- PyObject * msg = PyUnicode_FromString ("Missing parentheses in call "
3188- "to 'exec'" );
3189- if (msg == NULL ) {
3190- return -1 ;
3191- }
3192- Py_XSETREF (self -> msg , msg );
3193- return 1 ;
3194- }
3195- /* Fall back to the default error message */
3196- return 0 ;
3197- }
3198-
3199- static int
3200- _report_missing_parentheses (PySyntaxErrorObject * self )
3201- {
3202- Py_UCS4 left_paren = 40 ;
3203- Py_ssize_t left_paren_index ;
3204- Py_ssize_t text_len = PyUnicode_GET_LENGTH (self -> text );
3205- int legacy_check_result = 0 ;
3206-
3207- /* Skip entirely if there is an opening parenthesis */
3208- left_paren_index = PyUnicode_FindChar (self -> text , left_paren ,
3209- 0 , text_len , 1 );
3210- if (left_paren_index < -1 ) {
3211- return -1 ;
3212- }
3213- if (left_paren_index != -1 ) {
3214- /* Use default error message for any line with an opening paren */
3215- return 0 ;
3216- }
3217- /* Handle the simple statement case */
3218- legacy_check_result = _check_for_legacy_statements (self , 0 );
3219- if (legacy_check_result < 0 ) {
3220- return -1 ;
3221-
3222- }
3223- if (legacy_check_result == 0 ) {
3224- /* Handle the one-line complex statement case */
3225- Py_UCS4 colon = 58 ;
3226- Py_ssize_t colon_index ;
3227- colon_index = PyUnicode_FindChar (self -> text , colon ,
3228- 0 , text_len , 1 );
3229- if (colon_index < -1 ) {
3230- return -1 ;
3231- }
3232- if (colon_index >= 0 && colon_index < text_len ) {
3233- /* Check again, starting from just after the colon */
3234- if (_check_for_legacy_statements (self , colon_index + 1 ) < 0 ) {
3235- return -1 ;
3236- }
3237- }
3238- }
3239- return 0 ;
3240- }
0 commit comments