summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Objects/exceptions.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-04-18 12:39:32 +0300
committershadchin <[email protected]>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Objects/exceptions.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff)
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Objects/exceptions.c')
-rw-r--r--contrib/tools/python3/src/Objects/exceptions.c463
1 files changed, 212 insertions, 251 deletions
diff --git a/contrib/tools/python3/src/Objects/exceptions.c b/contrib/tools/python3/src/Objects/exceptions.c
index e67ecfab858..6537a7ccd1e 100644
--- a/contrib/tools/python3/src/Objects/exceptions.c
+++ b/contrib/tools/python3/src/Objects/exceptions.c
@@ -19,8 +19,13 @@ PyObject *PyExc_IOError = NULL;
PyObject *PyExc_WindowsError = NULL;
#endif
-/* The dict map from errno codes to OSError subclasses */
-static PyObject *errnomap = NULL;
+
+static struct _Py_exc_state*
+get_exc_state(void)
+{
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ return &interp->exc_state;
+}
/* NOTE: If the exception class hierarchy changes, don't forget to update
@@ -359,8 +364,6 @@ PyException_SetContext(PyObject *self, PyObject *context)
Py_XSETREF(_PyBaseExceptionObject_cast(self)->context, context);
}
-#undef PyExceptionClass_Name
-
const char *
PyExceptionClass_Name(PyObject *ob)
{
@@ -985,10 +988,11 @@ OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
))
goto error;
+ struct _Py_exc_state *state = get_exc_state();
if (myerrno && PyLong_Check(myerrno) &&
- errnomap && (PyObject *) type == PyExc_OSError) {
+ state->errnomap && (PyObject *) type == PyExc_OSError) {
PyObject *newtype;
- newtype = PyDict_GetItemWithError(errnomap, myerrno);
+ newtype = PyDict_GetItemWithError(state->errnomap, myerrno);
if (newtype) {
assert(PyType_Check(newtype));
type = (PyTypeObject *) newtype;
@@ -1322,29 +1326,155 @@ SimpleExtendsException(PyExc_RuntimeError, NotImplementedError,
/*
* NameError extends Exception
*/
-SimpleExtendsException(PyExc_Exception, NameError,
- "Name not found globally.");
+
+static int
+NameError_init(PyNameErrorObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = {"name", NULL};
+ PyObject *name = NULL;
+
+ if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) {
+ return -1;
+ }
+
+ PyObject *empty_tuple = PyTuple_New(0);
+ if (!empty_tuple) {
+ return -1;
+ }
+ if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$O:NameError", kwlist,
+ &name)) {
+ Py_DECREF(empty_tuple);
+ return -1;
+ }
+ Py_DECREF(empty_tuple);
+
+ Py_XINCREF(name);
+ Py_XSETREF(self->name, name);
+
+ return 0;
+}
+
+static int
+NameError_clear(PyNameErrorObject *self)
+{
+ Py_CLEAR(self->name);
+ return BaseException_clear((PyBaseExceptionObject *)self);
+}
+
+static void
+NameError_dealloc(PyNameErrorObject *self)
+{
+ _PyObject_GC_UNTRACK(self);
+ NameError_clear(self);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static int
+NameError_traverse(PyNameErrorObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->name);
+ return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
+}
+
+static PyMemberDef NameError_members[] = {
+ {"name", T_OBJECT, offsetof(PyNameErrorObject, name), 0, PyDoc_STR("name")},
+ {NULL} /* Sentinel */
+};
+
+static PyMethodDef NameError_methods[] = {
+ {NULL} /* Sentinel */
+};
+
+ComplexExtendsException(PyExc_Exception, NameError,
+ NameError, 0,
+ NameError_methods, NameError_members,
+ 0, BaseException_str, "Name not found globally.");
/*
* UnboundLocalError extends NameError
*/
-SimpleExtendsException(PyExc_NameError, UnboundLocalError,
+
+MiddlingExtendsException(PyExc_NameError, UnboundLocalError, NameError,
"Local name referenced but not bound to a value.");
/*
* AttributeError extends Exception
*/
-SimpleExtendsException(PyExc_Exception, AttributeError,
- "Attribute not found.");
+static int
+AttributeError_init(PyAttributeErrorObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = {"name", "obj", NULL};
+ PyObject *name = NULL;
+ PyObject *obj = NULL;
+
+ if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) {
+ return -1;
+ }
+
+ PyObject *empty_tuple = PyTuple_New(0);
+ if (!empty_tuple) {
+ return -1;
+ }
+ if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OO:AttributeError", kwlist,
+ &name, &obj)) {
+ Py_DECREF(empty_tuple);
+ return -1;
+ }
+ Py_DECREF(empty_tuple);
+
+ Py_XINCREF(name);
+ Py_XSETREF(self->name, name);
+
+ Py_XINCREF(obj);
+ Py_XSETREF(self->obj, obj);
+
+ return 0;
+}
+
+static int
+AttributeError_clear(PyAttributeErrorObject *self)
+{
+ Py_CLEAR(self->obj);
+ Py_CLEAR(self->name);
+ return BaseException_clear((PyBaseExceptionObject *)self);
+}
+
+static void
+AttributeError_dealloc(PyAttributeErrorObject *self)
+{
+ _PyObject_GC_UNTRACK(self);
+ AttributeError_clear(self);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static int
+AttributeError_traverse(PyAttributeErrorObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->obj);
+ Py_VISIT(self->name);
+ return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
+}
+
+static PyMemberDef AttributeError_members[] = {
+ {"name", T_OBJECT, offsetof(PyAttributeErrorObject, name), 0, PyDoc_STR("attribute name")},
+ {"obj", T_OBJECT, offsetof(PyAttributeErrorObject, obj), 0, PyDoc_STR("object")},
+ {NULL} /* Sentinel */
+};
+
+static PyMethodDef AttributeError_methods[] = {
+ {NULL} /* Sentinel */
+};
+
+ComplexExtendsException(PyExc_Exception, AttributeError,
+ AttributeError, 0,
+ AttributeError_methods, AttributeError_members,
+ 0, BaseException_str, "Attribute not found.");
/*
* SyntaxError extends Exception
*/
-/* Helper function to customize error message for some syntax errors */
-static int _report_missing_parentheses(PySyntaxErrorObject *self);
-
static int
SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
{
@@ -1361,39 +1491,30 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
if (lenargs == 2) {
info = PyTuple_GET_ITEM(args, 1);
info = PySequence_Tuple(info);
- if (!info)
+ if (!info) {
return -1;
+ }
- if (PyTuple_GET_SIZE(info) != 4) {
- /* not a very good error message, but it's what Python 2.4 gives */
- PyErr_SetString(PyExc_IndexError, "tuple index out of range");
+ self->end_lineno = NULL;
+ self->end_offset = NULL;
+ if (!PyArg_ParseTuple(info, "OOOO|OO",
+ &self->filename, &self->lineno,
+ &self->offset, &self->text,
+ &self->end_lineno, &self->end_offset)) {
Py_DECREF(info);
return -1;
}
- Py_INCREF(PyTuple_GET_ITEM(info, 0));
- Py_XSETREF(self->filename, PyTuple_GET_ITEM(info, 0));
-
- Py_INCREF(PyTuple_GET_ITEM(info, 1));
- Py_XSETREF(self->lineno, PyTuple_GET_ITEM(info, 1));
-
- Py_INCREF(PyTuple_GET_ITEM(info, 2));
- Py_XSETREF(self->offset, PyTuple_GET_ITEM(info, 2));
-
- Py_INCREF(PyTuple_GET_ITEM(info, 3));
- Py_XSETREF(self->text, PyTuple_GET_ITEM(info, 3));
-
+ Py_INCREF(self->filename);
+ Py_INCREF(self->lineno);
+ Py_INCREF(self->offset);
+ Py_INCREF(self->text);
+ Py_XINCREF(self->end_lineno);
+ Py_XINCREF(self->end_offset);
Py_DECREF(info);
- /*
- * Issue #21669: Custom error for 'print' & 'exec' as statements
- *
- * Only applies to SyntaxError instances, not to subclasses such
- * as TabError or IndentationError (see issue #31161)
- */
- if (Py_IS_TYPE(self, (PyTypeObject *)PyExc_SyntaxError) &&
- self->text && PyUnicode_Check(self->text) &&
- _report_missing_parentheses(self) < 0) {
+ if (self->end_lineno != NULL && self->end_offset == NULL) {
+ PyErr_SetString(PyExc_TypeError, "end_offset must be provided when end_lineno is provided");
return -1;
}
}
@@ -1407,6 +1528,8 @@ SyntaxError_clear(PySyntaxErrorObject *self)
Py_CLEAR(self->filename);
Py_CLEAR(self->lineno);
Py_CLEAR(self->offset);
+ Py_CLEAR(self->end_lineno);
+ Py_CLEAR(self->end_offset);
Py_CLEAR(self->text);
Py_CLEAR(self->print_file_and_line);
return BaseException_clear((PyBaseExceptionObject *)self);
@@ -1427,6 +1550,8 @@ SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg)
Py_VISIT(self->filename);
Py_VISIT(self->lineno);
Py_VISIT(self->offset);
+ Py_VISIT(self->end_lineno);
+ Py_VISIT(self->end_offset);
Py_VISIT(self->text);
Py_VISIT(self->print_file_and_line);
return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
@@ -1517,6 +1642,10 @@ static PyMemberDef SyntaxError_members[] = {
PyDoc_STR("exception offset")},
{"text", T_OBJECT, offsetof(PySyntaxErrorObject, text), 0,
PyDoc_STR("exception text")},
+ {"end_lineno", T_OBJECT, offsetof(PySyntaxErrorObject, end_lineno), 0,
+ PyDoc_STR("exception end lineno")},
+ {"end_offset", T_OBJECT, offsetof(PySyntaxErrorObject, end_offset), 0,
+ PyDoc_STR("exception end offset")},
{"print_file_and_line", T_OBJECT,
offsetof(PySyntaxErrorObject, print_file_and_line), 0,
PyDoc_STR("exception print_file_and_line")},
@@ -2274,8 +2403,6 @@ SimpleExtendsException(PyExc_Exception, ReferenceError,
*/
#define MEMERRORS_SAVE 16
-static PyBaseExceptionObject *memerrors_freelist = NULL;
-static int memerrors_numfree = 0;
static PyObject *
MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -2288,16 +2415,21 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return BaseException_new(type, args, kwds);
}
- if (memerrors_freelist == NULL)
+ struct _Py_exc_state *state = get_exc_state();
+ if (state->memerrors_freelist == NULL) {
return BaseException_new(type, args, kwds);
+ }
+
/* Fetch object from freelist and revive it */
- self = memerrors_freelist;
+ self = state->memerrors_freelist;
self->args = PyTuple_New(0);
/* This shouldn't happen since the empty tuple is persistent */
- if (self->args == NULL)
+ if (self->args == NULL) {
return NULL;
- memerrors_freelist = (PyBaseExceptionObject *) self->dict;
- memerrors_numfree--;
+ }
+
+ state->memerrors_freelist = (PyBaseExceptionObject *) self->dict;
+ state->memerrors_numfree--;
self->dict = NULL;
_Py_NewReference((PyObject *)self);
_PyObject_GC_TRACK(self);
@@ -2309,6 +2441,8 @@ MemoryError_dealloc(PyBaseExceptionObject *self)
{
BaseException_clear(self);
+ /* If this is a subclass of MemoryError, we don't need to
+ * do anything in the free-list*/
if (!Py_IS_TYPE(self, (PyTypeObject *) PyExc_MemoryError)) {
Py_TYPE(self)->tp_free((PyObject *)self);
return;
@@ -2316,12 +2450,14 @@ MemoryError_dealloc(PyBaseExceptionObject *self)
_PyObject_GC_UNTRACK(self);
- if (memerrors_numfree >= MEMERRORS_SAVE)
+ struct _Py_exc_state *state = get_exc_state();
+ if (state->memerrors_numfree >= MEMERRORS_SAVE) {
Py_TYPE(self)->tp_free((PyObject *)self);
+ }
else {
- self->dict = (PyObject *) memerrors_freelist;
- memerrors_freelist = self;
- memerrors_numfree++;
+ self->dict = (PyObject *) state->memerrors_freelist;
+ state->memerrors_freelist = self;
+ state->memerrors_numfree++;
}
}
@@ -2346,11 +2482,11 @@ preallocate_memerrors(void)
}
static void
-free_preallocated_memerrors(void)
+free_preallocated_memerrors(struct _Py_exc_state *state)
{
- while (memerrors_freelist != NULL) {
- PyObject *self = (PyObject *) memerrors_freelist;
- memerrors_freelist = (PyBaseExceptionObject *) memerrors_freelist->dict;
+ while (state->memerrors_freelist != NULL) {
+ PyObject *self = (PyObject *) state->memerrors_freelist;
+ state->memerrors_freelist = (PyBaseExceptionObject *)state->memerrors_freelist->dict;
Py_TYPE(self)->tp_free((PyObject *)self);
}
}
@@ -2454,6 +2590,13 @@ SimpleExtendsException(PyExc_Warning, BytesWarning,
/*
+ * EncodingWarning extends Warning
+ */
+SimpleExtendsException(PyExc_Warning, EncodingWarning,
+ "Base class for warnings about encodings.");
+
+
+/*
* ResourceWarning extends Warning
*/
SimpleExtendsException(PyExc_Warning, ResourceWarning,
@@ -2518,8 +2661,10 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
#endif /* MS_WINDOWS */
PyStatus
-_PyExc_Init(void)
+_PyExc_Init(PyInterpreterState *interp)
{
+ struct _Py_exc_state *state = &interp->exc_state;
+
#define PRE_INIT(TYPE) \
if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \
if (PyType_Ready(&_PyExc_ ## TYPE) < 0) { \
@@ -2532,7 +2677,7 @@ _PyExc_Init(void)
do { \
PyObject *_code = PyLong_FromLong(CODE); \
assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \
- if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) { \
+ if (!_code || PyDict_SetItem(state->errnomap, _code, PyExc_ ## TYPE)) { \
Py_XDECREF(_code); \
return _PyStatus_ERR("errmap insertion problem."); \
} \
@@ -2579,6 +2724,7 @@ _PyExc_Init(void)
PRE_INIT(BufferError);
PRE_INIT(Warning);
PRE_INIT(UserWarning);
+ PRE_INIT(EncodingWarning);
PRE_INIT(DeprecationWarning);
PRE_INIT(PendingDeprecationWarning);
PRE_INIT(SyntaxWarning);
@@ -2608,15 +2754,14 @@ _PyExc_Init(void)
PRE_INIT(TimeoutError);
if (preallocate_memerrors() < 0) {
- return _PyStatus_ERR("Could not preallocate MemoryError object");
+ return _PyStatus_NO_MEMORY();
}
/* Add exceptions to errnomap */
- if (!errnomap) {
- errnomap = PyDict_New();
- if (!errnomap) {
- return _PyStatus_ERR("Cannot allocate map from errnos to OSError subclasses");
- }
+ assert(state->errnomap == NULL);
+ state->errnomap = PyDict_New();
+ if (!state->errnomap) {
+ return _PyStatus_NO_MEMORY();
}
ADD_ERRNO(BlockingIOError, EAGAIN);
@@ -2719,6 +2864,7 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod)
POST_INIT(BufferError);
POST_INIT(Warning);
POST_INIT(UserWarning);
+ POST_INIT(EncodingWarning);
POST_INIT(DeprecationWarning);
POST_INIT(PendingDeprecationWarning);
POST_INIT(SyntaxWarning);
@@ -2754,10 +2900,11 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod)
}
void
-_PyExc_Fini(void)
+_PyExc_Fini(PyInterpreterState *interp)
{
- free_preallocated_memerrors();
- Py_CLEAR(errnomap);
+ struct _Py_exc_state *state = &interp->exc_state;
+ free_preallocated_memerrors(state);
+ Py_CLEAR(state->errnomap);
}
/* Helper to do the equivalent of "raise X from Y" in C, but always using
@@ -2890,189 +3037,3 @@ _PyErr_TrySetFromCause(const char *format, ...)
PyErr_Restore(new_exc, new_val, new_tb);
return new_val;
}
-
-
-/* To help with migration from Python 2, SyntaxError.__init__ applies some
- * heuristics to try to report a more meaningful exception when print and
- * exec are used like statements.
- *
- * The heuristics are currently expected to detect the following cases:
- * - top level statement
- * - statement in a nested suite
- * - trailing section of a one line complex statement
- *
- * They're currently known not to trigger:
- * - after a semi-colon
- *
- * The error message can be a bit odd in cases where the "arguments" are
- * completely illegal syntactically, but that isn't worth the hassle of
- * fixing.
- *
- * We also can't do anything about cases that are legal Python 3 syntax
- * but mean something entirely different from what they did in Python 2
- * (omitting the arguments entirely, printing items preceded by a unary plus
- * 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)
-{
- // PRINT_OFFSET is to remove the `print ` prefix from the data.
- const int PRINT_OFFSET = 6;
- const int STRIP_BOTH = 2;
- 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;
- }
-
- PyObject *data = PyUnicode_Substring(self->text, start_pos, end_pos);
- if (data == NULL) {
- 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);
- 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)
-{
- /* Return values:
- * -1: an error occurred
- * 0: nothing happened
- * 1: the check triggered & the error message was changed
- */
- static PyObject *print_prefix = NULL;
- static PyObject *exec_prefix = NULL;
- Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text), match;
- int kind = PyUnicode_KIND(self->text);
- const void *data = PyUnicode_DATA(self->text);
-
- /* Ignore leading whitespace */
- while (start < text_len) {
- Py_UCS4 ch = PyUnicode_READ(kind, data, start);
- if (!Py_UNICODE_ISSPACE(ch))
- break;
- start++;
- }
- /* Checking against an empty or whitespace-only part of the string */
- if (start == text_len) {
- return 0;
- }
-
- /* Check for legacy print statements */
- if (print_prefix == NULL) {
- print_prefix = PyUnicode_InternFromString("print ");
- if (print_prefix == NULL) {
- return -1;
- }
- }
- match = PyUnicode_Tailmatch(self->text, print_prefix,
- start, text_len, -1);
- if (match == -1) {
- return -1;
- }
- if (match) {
- return _set_legacy_print_statement_msg(self, start);
- }
-
- /* Check for legacy exec statements */
- if (exec_prefix == NULL) {
- exec_prefix = PyUnicode_InternFromString("exec ");
- if (exec_prefix == NULL) {
- return -1;
- }
- }
- match = PyUnicode_Tailmatch(self->text, exec_prefix, start, text_len, -1);
- if (match == -1) {
- return -1;
- }
- if (match) {
- PyObject *msg = PyUnicode_FromString("Missing parentheses in call "
- "to 'exec'");
- if (msg == NULL) {
- return -1;
- }
- Py_XSETREF(self->msg, msg);
- return 1;
- }
- /* Fall back to the default error message */
- return 0;
-}
-
-static int
-_report_missing_parentheses(PySyntaxErrorObject *self)
-{
- Py_UCS4 left_paren = 40;
- Py_ssize_t left_paren_index;
- Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text);
- int legacy_check_result = 0;
-
- /* Skip entirely if there is an opening parenthesis */
- left_paren_index = PyUnicode_FindChar(self->text, left_paren,
- 0, text_len, 1);
- if (left_paren_index < -1) {
- return -1;
- }
- if (left_paren_index != -1) {
- /* Use default error message for any line with an opening paren */
- return 0;
- }
- /* Handle the simple statement case */
- legacy_check_result = _check_for_legacy_statements(self, 0);
- if (legacy_check_result < 0) {
- return -1;
-
- }
- if (legacy_check_result == 0) {
- /* Handle the one-line complex statement case */
- Py_UCS4 colon = 58;
- Py_ssize_t colon_index;
- colon_index = PyUnicode_FindChar(self->text, colon,
- 0, text_len, 1);
- if (colon_index < -1) {
- return -1;
- }
- if (colon_index >= 0 && colon_index < text_len) {
- /* Check again, starting from just after the colon */
- if (_check_for_legacy_statements(self, colon_index+1) < 0) {
- return -1;
- }
- }
- }
- return 0;
-}