/home/mdboom/Work/builds/cpython/Objects/exceptions.c
Line | Count | Source (jump to first uncovered line) |
1 | /* |
2 | * New exceptions.c written in Iceland by Richard Jones and Georg Brandl. |
3 | * |
4 | * Thanks go to Tim Peters and Michael Hudson for debugging. |
5 | */ |
6 | |
7 | #define PY_SSIZE_T_CLEAN |
8 | #include <Python.h> |
9 | #include <stdbool.h> |
10 | #include "pycore_ceval.h" // _Py_EnterRecursiveCall |
11 | #include "pycore_exceptions.h" // struct _Py_exc_state |
12 | #include "pycore_initconfig.h" |
13 | #include "pycore_object.h" |
14 | #include "structmember.h" // PyMemberDef |
15 | #include "osdefs.h" // SEP |
16 | |
17 | |
18 | /* Compatibility aliases */ |
19 | PyObject *PyExc_EnvironmentError = NULL; // borrowed ref |
20 | PyObject *PyExc_IOError = NULL; // borrowed ref |
21 | #ifdef MS_WINDOWS |
22 | PyObject *PyExc_WindowsError = NULL; // borrowed ref |
23 | #endif |
24 | |
25 | |
26 | static struct _Py_exc_state* |
27 | get_exc_state(void) |
28 | { |
29 | PyInterpreterState *interp = _PyInterpreterState_GET(); |
30 | return &interp->exc_state; |
31 | } |
32 | |
33 | |
34 | /* NOTE: If the exception class hierarchy changes, don't forget to update |
35 | * Lib/test/exception_hierarchy.txt |
36 | */ |
37 | |
38 | /* |
39 | * BaseException |
40 | */ |
41 | static PyObject * |
42 | BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
43 | { |
44 | PyBaseExceptionObject *self; |
45 | |
46 | self = (PyBaseExceptionObject *)type->tp_alloc(type, 0); |
47 | if (!self) Branch (47:9): [True: 0, False: 2.98M]
|
48 | return NULL; |
49 | /* the dict is created on the fly in PyObject_GenericSetAttr */ |
50 | self->dict = NULL; |
51 | self->notes = NULL; |
52 | self->traceback = self->cause = self->context = NULL; |
53 | self->suppress_context = 0; |
54 | |
55 | if (args) { Branch (55:9): [True: 2.98M, False: 1.71k]
|
56 | self->args = args; |
57 | Py_INCREF(args); |
58 | return (PyObject *)self; |
59 | } |
60 | |
61 | self->args = PyTuple_New(0); |
62 | if (!self->args) { Branch (62:9): [True: 0, False: 1.71k]
|
63 | Py_DECREF(self); |
64 | return NULL; |
65 | } |
66 | |
67 | return (PyObject *)self; |
68 | } |
69 | |
70 | static int |
71 | BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds) |
72 | { |
73 | if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds)) |
74 | return -1; |
75 | |
76 | Py_INCREF(args); |
77 | Py_XSETREF(self->args, args); |
78 | |
79 | return 0; |
80 | } |
81 | |
82 | static int |
83 | BaseException_clear(PyBaseExceptionObject *self) |
84 | { |
85 | Py_CLEAR(self->dict); |
86 | Py_CLEAR(self->args); |
87 | Py_CLEAR(self->notes); |
88 | Py_CLEAR(self->traceback); |
89 | Py_CLEAR(self->cause); |
90 | Py_CLEAR(self->context); |
91 | return 0; |
92 | } |
93 | |
94 | static void |
95 | BaseException_dealloc(PyBaseExceptionObject *self) |
96 | { |
97 | PyObject_GC_UnTrack(self); |
98 | // bpo-44348: The trashcan mechanism prevents stack overflow when deleting |
99 | // long chains of exceptions. For example, exceptions can be chained |
100 | // through the __context__ attributes or the __traceback__ attribute. |
101 | Py_TRASHCAN_BEGIN(self, BaseException_dealloc) |
102 | BaseException_clear(self); |
103 | Py_TYPE(self)->tp_free((PyObject *)self); |
104 | Py_TRASHCAN_END |
105 | } |
106 | |
107 | static int |
108 | BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg) |
109 | { |
110 | Py_VISIT(self->dict); |
111 | Py_VISIT(self->args); |
112 | Py_VISIT(self->notes); |
113 | Py_VISIT(self->traceback); |
114 | Py_VISIT(self->cause); |
115 | Py_VISIT(self->context); |
116 | return 0; |
117 | } |
118 | |
119 | static PyObject * |
120 | BaseException_str(PyBaseExceptionObject *self) |
121 | { |
122 | switch (PyTuple_GET_SIZE(self->args)) { |
123 | case 0: Branch (123:5): [True: 195, False: 19.9k]
|
124 | return PyUnicode_FromString(""); |
125 | case 1: Branch (125:5): [True: 19.8k, False: 216]
|
126 | return PyObject_Str(PyTuple_GET_ITEM(self->args, 0)); |
127 | default: Branch (127:5): [True: 21, False: 20.0k]
|
128 | return PyObject_Str(self->args); |
129 | } |
130 | } |
131 | |
132 | static PyObject * |
133 | BaseException_repr(PyBaseExceptionObject *self) |
134 | { |
135 | const char *name = _PyType_Name(Py_TYPE(self)); |
136 | if (PyTuple_GET_SIZE(self->args) == 1) Branch (136:9): [True: 1.62k, False: 548]
|
137 | return PyUnicode_FromFormat("%s(%R)", name, |
138 | PyTuple_GET_ITEM(self->args, 0)); |
139 | else |
140 | return PyUnicode_FromFormat("%s%R", name, self->args); |
141 | } |
142 | |
143 | /* Pickling support */ |
144 | static PyObject * |
145 | BaseException_reduce(PyBaseExceptionObject *self, PyObject *Py_UNUSED(ignored)) |
146 | { |
147 | if (self->args && self->dict) Branch (147:9): [True: 221, False: 0]
Branch (147:23): [True: 80, False: 141]
|
148 | return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict); |
149 | else |
150 | return PyTuple_Pack(2, Py_TYPE(self), self->args); |
151 | } |
152 | |
153 | /* |
154 | * Needed for backward compatibility, since exceptions used to store |
155 | * all their attributes in the __dict__. Code is taken from cPickle's |
156 | * load_build function. |
157 | */ |
158 | static PyObject * |
159 | BaseException_setstate(PyObject *self, PyObject *state) |
160 | { |
161 | PyObject *d_key, *d_value; |
162 | Py_ssize_t i = 0; |
163 | |
164 | if (state != Py_None) { Branch (164:9): [True: 164, False: 0]
|
165 | if (!PyDict_Check(state)) { Branch (165:13): [True: 0, False: 164]
|
166 | PyErr_SetString(PyExc_TypeError, "state is not a dictionary"); |
167 | return NULL; |
168 | } |
169 | while (164 PyDict_Next(state, &i, &d_key, &d_value)) { Branch (169:16): [True: 388, False: 164]
|
170 | if (PyObject_SetAttr(self, d_key, d_value) < 0) Branch (170:17): [True: 0, False: 388]
|
171 | return NULL; |
172 | } |
173 | } |
174 | Py_RETURN_NONE; |
175 | } |
176 | |
177 | static PyObject * |
178 | BaseException_with_traceback(PyObject *self, PyObject *tb) { |
179 | if (PyException_SetTraceback(self, tb)) Branch (179:9): [True: 0, False: 185k]
|
180 | return NULL; |
181 | |
182 | Py_INCREF(self); |
183 | return self; |
184 | } |
185 | |
186 | PyDoc_STRVAR(with_traceback_doc, |
187 | "Exception.with_traceback(tb) --\n\ |
188 | set self.__traceback__ to tb and return self."); |
189 | |
190 | static inline PyBaseExceptionObject* |
191 | _PyBaseExceptionObject_cast(PyObject *exc) |
192 | { |
193 | assert(PyExceptionInstance_Check(exc)); |
194 | return (PyBaseExceptionObject *)exc; |
195 | } |
196 | |
197 | static PyObject * |
198 | BaseException_add_note(PyObject *self, PyObject *note) |
199 | { |
200 | if (!PyUnicode_Check(note)) { Branch (200:9): [True: 3, False: 54]
|
201 | PyErr_Format(PyExc_TypeError, |
202 | "note must be a str, not '%s'", |
203 | Py_TYPE(note)->tp_name); |
204 | return NULL; |
205 | } |
206 | |
207 | if (!PyObject_HasAttr(self, &_Py_ID(__notes__))) { Branch (207:9): [True: 32, False: 22]
|
208 | PyObject *new_notes = PyList_New(0); |
209 | if (new_notes == NULL) { Branch (209:13): [True: 0, False: 32]
|
210 | return NULL; |
211 | } |
212 | if (PyObject_SetAttr(self, &_Py_ID(__notes__), new_notes) < 0) { Branch (212:13): [True: 0, False: 32]
|
213 | Py_DECREF(new_notes); |
214 | return NULL; |
215 | } |
216 | Py_DECREF(new_notes); |
217 | } |
218 | PyObject *notes = PyObject_GetAttr(self, &_Py_ID(__notes__)); |
219 | if (notes == NULL) { Branch (219:9): [True: 0, False: 54]
|
220 | return NULL; |
221 | } |
222 | if (!PyList_Check(notes)) { Branch (222:9): [True: 3, False: 51]
|
223 | Py_DECREF(notes); |
224 | PyErr_SetString(PyExc_TypeError, "Cannot add note: __notes__ is not a list"); |
225 | return NULL; |
226 | } |
227 | if (PyList_Append(notes, note) < 0) { Branch (227:9): [True: 0, False: 51]
|
228 | Py_DECREF(notes); |
229 | return NULL; |
230 | } |
231 | Py_DECREF(notes); |
232 | Py_RETURN_NONE; |
233 | } |
234 | |
235 | PyDoc_STRVAR(add_note_doc, |
236 | "Exception.add_note(note) --\n\ |
237 | add a note to the exception"); |
238 | |
239 | static PyMethodDef BaseException_methods[] = { |
240 | {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS }, |
241 | {"__setstate__", (PyCFunction)BaseException_setstate, METH_O }, |
242 | {"with_traceback", (PyCFunction)BaseException_with_traceback, METH_O, |
243 | with_traceback_doc}, |
244 | {"add_note", (PyCFunction)BaseException_add_note, METH_O, |
245 | add_note_doc}, |
246 | {NULL, NULL, 0, NULL}, |
247 | }; |
248 | |
249 | static PyObject * |
250 | BaseException_get_args(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) |
251 | { |
252 | if (self->args == NULL) { Branch (252:9): [True: 0, False: 7.63k]
|
253 | Py_RETURN_NONE; |
254 | } |
255 | Py_INCREF(self->args); |
256 | return self->args; |
257 | } |
258 | |
259 | static int |
260 | BaseException_set_args(PyBaseExceptionObject *self, PyObject *val, void *Py_UNUSED(ignored)) |
261 | { |
262 | PyObject *seq; |
263 | if (val == NULL) { Branch (263:9): [True: 0, False: 1.26k]
|
264 | PyErr_SetString(PyExc_TypeError, "args may not be deleted"); |
265 | return -1; |
266 | } |
267 | seq = PySequence_Tuple(val); |
268 | if (!seq) Branch (268:9): [True: 0, False: 1.26k]
|
269 | return -1; |
270 | Py_XSETREF(self->args, seq); |
271 | return 0; |
272 | } |
273 | |
274 | static PyObject * |
275 | BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) |
276 | { |
277 | if (self->traceback == NULL) { Branch (277:9): [True: 10.2k, False: 4.09k]
|
278 | Py_RETURN_NONE; |
279 | } |
280 | Py_INCREF(self->traceback); |
281 | return self->traceback; |
282 | } |
283 | |
284 | static int |
285 | BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(ignored)) |
286 | { |
287 | if (tb == NULL) { Branch (287:9): [True: 0, False: 3.41M]
|
288 | PyErr_SetString(PyExc_TypeError, "__traceback__ may not be deleted"); |
289 | return -1; |
290 | } |
291 | else if (!(tb == Py_None || PyTraceBack_Check(tb))) { Branch (291:16): [True: 185k, False: 3.23M]
|
292 | PyErr_SetString(PyExc_TypeError, |
293 | "__traceback__ must be a traceback or None"); |
294 | return -1; |
295 | } |
296 | |
297 | Py_INCREF(tb); |
298 | Py_XSETREF(self->traceback, tb); |
299 | return 0; |
300 | } |
301 | |
302 | static PyObject * |
303 | BaseException_get_context(PyObject *self, void *Py_UNUSED(ignored)) |
304 | { |
305 | PyObject *res = PyException_GetContext(self); |
306 | if (res) Branch (306:9): [True: 6.45k, False: 13.1k]
|
307 | return res; /* new reference already returned above */ |
308 | Py_RETURN_NONE13.1k ; |
309 | } |
310 | |
311 | static int |
312 | BaseException_set_context(PyObject *self, PyObject *arg, void *Py_UNUSED(ignored)) |
313 | { |
314 | if (arg == NULL) { Branch (314:9): [True: 1, False: 130]
|
315 | PyErr_SetString(PyExc_TypeError, "__context__ may not be deleted"); |
316 | return -1; |
317 | } else if (arg == Py_None) { Branch (317:16): [True: 100, False: 30]
|
318 | arg = NULL; |
319 | } else if (30 !30 PyExceptionInstance_Check30 (arg)) { Branch (319:16): [True: 1, False: 29]
|
320 | PyErr_SetString(PyExc_TypeError, "exception context must be None " |
321 | "or derive from BaseException"); |
322 | return -1; |
323 | } else { |
324 | /* PyException_SetContext steals this reference */ |
325 | Py_INCREF(arg); |
326 | } |
327 | PyException_SetContext(self, arg); |
328 | return 0; |
329 | } |
330 | |
331 | static PyObject * |
332 | BaseException_get_cause(PyObject *self, void *Py_UNUSED(ignored)) |
333 | { |
334 | PyObject *res = PyException_GetCause(self); |
335 | if (res) Branch (335:9): [True: 210, False: 13.7k]
|
336 | return res; /* new reference already returned above */ |
337 | Py_RETURN_NONE13.7k ; |
338 | } |
339 | |
340 | static int |
341 | BaseException_set_cause(PyObject *self, PyObject *arg, void *Py_UNUSED(ignored)) |
342 | { |
343 | if (arg == NULL) { Branch (343:9): [True: 1, False: 293]
|
344 | PyErr_SetString(PyExc_TypeError, "__cause__ may not be deleted"); |
345 | return -1; |
346 | } else if (arg == Py_None) { Branch (346:16): [True: 1, False: 292]
|
347 | arg = NULL; |
348 | } else if (!PyExceptionInstance_Check(arg)) { Branch (348:16): [True: 1, False: 291]
|
349 | PyErr_SetString(PyExc_TypeError, "exception cause must be None " |
350 | "or derive from BaseException"); |
351 | return -1; |
352 | } else { |
353 | /* PyException_SetCause steals this reference */ |
354 | Py_INCREF(arg); |
355 | } |
356 | PyException_SetCause(self, arg); |
357 | return 0; |
358 | } |
359 | |
360 | |
361 | static PyGetSetDef BaseException_getset[] = { |
362 | {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, |
363 | {"args", (getter)BaseException_get_args, (setter)BaseException_set_args}, |
364 | {"__traceback__", (getter)BaseException_get_tb, (setter)BaseException_set_tb}, |
365 | {"__context__", BaseException_get_context, |
366 | BaseException_set_context, PyDoc_STR("exception context")}, |
367 | {"__cause__", BaseException_get_cause, |
368 | BaseException_set_cause, PyDoc_STR("exception cause")}, |
369 | {NULL}, |
370 | }; |
371 | |
372 | |
373 | PyObject * |
374 | PyException_GetTraceback(PyObject *self) |
375 | { |
376 | PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self); |
377 | Py_XINCREF(base_self->traceback); |
378 | return base_self->traceback; |
379 | } |
380 | |
381 | |
382 | int |
383 | PyException_SetTraceback(PyObject *self, PyObject *tb) |
384 | { |
385 | return BaseException_set_tb(_PyBaseExceptionObject_cast(self), tb, NULL); |
386 | } |
387 | |
388 | PyObject * |
389 | PyException_GetCause(PyObject *self) |
390 | { |
391 | PyObject *cause = _PyBaseExceptionObject_cast(self)->cause; |
392 | Py_XINCREF(cause); |
393 | return cause; |
394 | } |
395 | |
396 | /* Steals a reference to cause */ |
397 | void |
398 | PyException_SetCause(PyObject *self, PyObject *cause) |
399 | { |
400 | PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self); |
401 | base_self->suppress_context = 1; |
402 | Py_XSETREF(base_self->cause, cause); |
403 | } |
404 | |
405 | PyObject * |
406 | PyException_GetContext(PyObject *self) |
407 | { |
408 | PyObject *context = _PyBaseExceptionObject_cast(self)->context; |
409 | Py_XINCREF(context); |
410 | return context; |
411 | } |
412 | |
413 | /* Steals a reference to context */ |
414 | void |
415 | PyException_SetContext(PyObject *self, PyObject *context) |
416 | { |
417 | Py_XSETREF(_PyBaseExceptionObject_cast(self)->context, context); |
418 | } |
419 | |
420 | const char * |
421 | PyExceptionClass_Name(PyObject *ob) |
422 | { |
423 | assert(PyExceptionClass_Check(ob)); |
424 | return ((PyTypeObject*)ob)->tp_name; |
425 | } |
426 | |
427 | static struct PyMemberDef BaseException_members[] = { |
428 | {"__suppress_context__", T_BOOL, |
429 | offsetof(PyBaseExceptionObject, suppress_context)}, |
430 | {NULL} |
431 | }; |
432 | |
433 | |
434 | static PyTypeObject _PyExc_BaseException = { |
435 | PyVarObject_HEAD_INIT(NULL, 0) |
436 | "BaseException", /*tp_name*/ |
437 | sizeof(PyBaseExceptionObject), /*tp_basicsize*/ |
438 | 0, /*tp_itemsize*/ |
439 | (destructor)BaseException_dealloc, /*tp_dealloc*/ |
440 | 0, /*tp_vectorcall_offset*/ |
441 | 0, /*tp_getattr*/ |
442 | 0, /*tp_setattr*/ |
443 | 0, /*tp_as_async*/ |
444 | (reprfunc)BaseException_repr, /*tp_repr*/ |
445 | 0, /*tp_as_number*/ |
446 | 0, /*tp_as_sequence*/ |
447 | 0, /*tp_as_mapping*/ |
448 | 0, /*tp_hash */ |
449 | 0, /*tp_call*/ |
450 | (reprfunc)BaseException_str, /*tp_str*/ |
451 | PyObject_GenericGetAttr, /*tp_getattro*/ |
452 | PyObject_GenericSetAttr, /*tp_setattro*/ |
453 | 0, /*tp_as_buffer*/ |
454 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | |
455 | Py_TPFLAGS_BASE_EXC_SUBCLASS, /*tp_flags*/ |
456 | PyDoc_STR("Common base class for all exceptions"), /* tp_doc */ |
457 | (traverseproc)BaseException_traverse, /* tp_traverse */ |
458 | (inquiry)BaseException_clear, /* tp_clear */ |
459 | 0, /* tp_richcompare */ |
460 | 0, /* tp_weaklistoffset */ |
461 | 0, /* tp_iter */ |
462 | 0, /* tp_iternext */ |
463 | BaseException_methods, /* tp_methods */ |
464 | BaseException_members, /* tp_members */ |
465 | BaseException_getset, /* tp_getset */ |
466 | 0, /* tp_base */ |
467 | 0, /* tp_dict */ |
468 | 0, /* tp_descr_get */ |
469 | 0, /* tp_descr_set */ |
470 | offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */ |
471 | (initproc)BaseException_init, /* tp_init */ |
472 | 0, /* tp_alloc */ |
473 | BaseException_new, /* tp_new */ |
474 | }; |
475 | /* the CPython API expects exceptions to be (PyObject *) - both a hold-over |
476 | from the previous implementation and also allowing Python objects to be used |
477 | in the API */ |
478 | PyObject *PyExc_BaseException = (PyObject *)&_PyExc_BaseException; |
479 | |
480 | /* note these macros omit the last semicolon so the macro invocation may |
481 | * include it and not look strange. |
482 | */ |
483 | #define SimpleExtendsException(EXCBASE, EXCNAME, EXCDOC) \ |
484 | static PyTypeObject _PyExc_ ## EXCNAME = { \ |
485 | PyVarObject_HEAD_INIT(NULL, 0) \ |
486 | # EXCNAME, \ |
487 | sizeof(PyBaseExceptionObject), \ |
488 | 0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \ |
489 | 0, 0, 0, 0, 0, 0, 0, \ |
490 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \ |
491 | PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \ |
492 | (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \ |
493 | 0, 0, 0, offsetof(PyBaseExceptionObject, dict), \ |
494 | (initproc)BaseException_init, 0, BaseException_new,\ |
495 | }; \ |
496 | PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME |
497 | |
498 | #define MiddlingExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDOC) \ |
499 | static PyTypeObject _PyExc_ ## EXCNAME = { \ |
500 | PyVarObject_HEAD_INIT(NULL, 0) \ |
501 | # EXCNAME, \ |
502 | sizeof(Py ## EXCSTORE ## Object), \ |
503 | 0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ |
504 | 0, 0, 0, 0, 0, \ |
505 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \ |
506 | PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \ |
507 | (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \ |
508 | 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \ |
509 | (initproc)EXCSTORE ## _init, 0, 0, \ |
510 | }; \ |
511 | PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME |
512 | |
513 | #define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCNEW, \ |
514 | EXCMETHODS, EXCMEMBERS, EXCGETSET, \ |
515 | EXCSTR, EXCDOC) \ |
516 | static PyTypeObject _PyExc_ ## EXCNAME = { \ |
517 | PyVarObject_HEAD_INIT(NULL, 0) \ |
518 | # EXCNAME, \ |
519 | sizeof(Py ## EXCSTORE ## Object), 0, \ |
520 | (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ |
521 | (reprfunc)EXCSTR, 0, 0, 0, \ |
522 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \ |
523 | PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \ |
524 | (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \ |
525 | EXCMEMBERS, EXCGETSET, &_ ## EXCBASE, \ |
526 | 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \ |
527 | (initproc)EXCSTORE ## _init, 0, EXCNEW,\ |
528 | }; \ |
529 | PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME |
530 | |
531 | |
532 | /* |
533 | * Exception extends BaseException |
534 | */ |
535 | SimpleExtendsException(PyExc_BaseException, Exception, |
536 | "Common base class for all non-exit exceptions."); |
537 | |
538 | |
539 | /* |
540 | * TypeError extends Exception |
541 | */ |
542 | SimpleExtendsException(PyExc_Exception, TypeError, |
543 | "Inappropriate argument type."); |
544 | |
545 | |
546 | /* |
547 | * StopAsyncIteration extends Exception |
548 | */ |
549 | SimpleExtendsException(PyExc_Exception, StopAsyncIteration, |
550 | "Signal the end from iterator.__anext__()."); |
551 | |
552 | |
553 | /* |
554 | * StopIteration extends Exception |
555 | */ |
556 | |
557 | static PyMemberDef StopIteration_members[] = { |
558 | {"value", T_OBJECT, offsetof(PyStopIterationObject, value), 0, |
559 | PyDoc_STR("generator return value")}, |
560 | {NULL} /* Sentinel */ |
561 | }; |
562 | |
563 | static int |
564 | StopIteration_init(PyStopIterationObject *self, PyObject *args, PyObject *kwds) |
565 | { |
566 | Py_ssize_t size = PyTuple_GET_SIZE(args); |
567 | PyObject *value; |
568 | |
569 | if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) Branch (569:9): [True: 0, False: 665k]
|
570 | return -1; |
571 | Py_CLEAR(self->value); |
572 | if (size > 0) Branch (572:9): [True: 844, False: 664k]
|
573 | value = PyTuple_GET_ITEM(args, 0); |
574 | else |
575 | value = Py_None; |
576 | Py_INCREF(value); |
577 | self->value = value; |
578 | return 0; |
579 | } |
580 | |
581 | static int |
582 | StopIteration_clear(PyStopIterationObject *self) |
583 | { |
584 | Py_CLEAR(self->value); |
585 | return BaseException_clear((PyBaseExceptionObject *)self); |
586 | } |
587 | |
588 | static void |
589 | StopIteration_dealloc(PyStopIterationObject *self) |
590 | { |
591 | PyObject_GC_UnTrack(self); |
592 | StopIteration_clear(self); |
593 | Py_TYPE(self)->tp_free((PyObject *)self); |
594 | } |
595 | |
596 | static int |
597 | StopIteration_traverse(PyStopIterationObject *self, visitproc visit, void *arg) |
598 | { |
599 | Py_VISIT(self->value); |
600 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
601 | } |
602 | |
603 | ComplexExtendsException( |
604 | PyExc_Exception, /* base */ |
605 | StopIteration, /* name */ |
606 | StopIteration, /* prefix for *_init, etc */ |
607 | 0, /* new */ |
608 | 0, /* methods */ |
609 | StopIteration_members, /* members */ |
610 | 0, /* getset */ |
611 | 0, /* str */ |
612 | "Signal the end from iterator.__next__()." |
613 | ); |
614 | |
615 | |
616 | /* |
617 | * GeneratorExit extends BaseException |
618 | */ |
619 | SimpleExtendsException(PyExc_BaseException, GeneratorExit, |
620 | "Request that a generator exit."); |
621 | |
622 | |
623 | /* |
624 | * SystemExit extends BaseException |
625 | */ |
626 | |
627 | static int |
628 | SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds) |
629 | { |
630 | Py_ssize_t size = PyTuple_GET_SIZE(args); |
631 | |
632 | if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) Branch (632:9): [True: 0, False: 2.29k]
|
633 | return -1; |
634 | |
635 | if (size == 0) Branch (635:9): [True: 21, False: 2.27k]
|
636 | return 0; |
637 | if (size == 1) { Branch (637:9): [True: 2.27k, False: 1]
|
638 | Py_INCREF(PyTuple_GET_ITEM(args, 0)); |
639 | Py_XSETREF(self->code, PyTuple_GET_ITEM(args, 0)); |
640 | } |
641 | else { /* size > 1 */ |
642 | Py_INCREF(args); |
643 | Py_XSETREF(self->code, args); |
644 | } |
645 | return 0; |
646 | } |
647 | |
648 | static int |
649 | SystemExit_clear(PySystemExitObject *self) |
650 | { |
651 | Py_CLEAR(self->code); |
652 | return BaseException_clear((PyBaseExceptionObject *)self); |
653 | } |
654 | |
655 | static void |
656 | SystemExit_dealloc(PySystemExitObject *self) |
657 | { |
658 | _PyObject_GC_UNTRACK(self); |
659 | SystemExit_clear(self); |
660 | Py_TYPE(self)->tp_free((PyObject *)self); |
661 | } |
662 | |
663 | static int |
664 | SystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg) |
665 | { |
666 | Py_VISIT(self->code); |
667 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
668 | } |
669 | |
670 | static PyMemberDef SystemExit_members[] = { |
671 | {"code", T_OBJECT, offsetof(PySystemExitObject, code), 0, |
672 | PyDoc_STR("exception code")}, |
673 | {NULL} /* Sentinel */ |
674 | }; |
675 | |
676 | ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit, |
677 | 0, 0, SystemExit_members, 0, 0, |
678 | "Request to exit from the interpreter."); |
679 | |
680 | /* |
681 | * BaseExceptionGroup extends BaseException |
682 | * ExceptionGroup extends BaseExceptionGroup and Exception |
683 | */ |
684 | |
685 | |
686 | static inline PyBaseExceptionGroupObject* |
687 | _PyBaseExceptionGroupObject_cast(PyObject *exc) |
688 | { |
689 | assert(_PyBaseExceptionGroup_Check(exc)); |
690 | return (PyBaseExceptionGroupObject *)exc; |
691 | } |
692 | |
693 | static PyObject * |
694 | BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
695 | { |
696 | struct _Py_exc_state *state = get_exc_state(); |
697 | PyTypeObject *PyExc_ExceptionGroup = |
698 | (PyTypeObject*)state->PyExc_ExceptionGroup; |
699 | |
700 | PyObject *message = NULL; |
701 | PyObject *exceptions = NULL; |
702 | |
703 | if (!PyArg_ParseTuple(args, Branch (703:9): [True: 7, False: 10.7k]
|
704 | "UO:BaseExceptionGroup.__new__", |
705 | &message, |
706 | &exceptions)) { |
707 | return NULL; |
708 | } |
709 | |
710 | if (!PySequence_Check(exceptions)) { Branch (710:9): [True: 2, False: 10.7k]
|
711 | PyErr_SetString( |
712 | PyExc_TypeError, |
713 | "second argument (exceptions) must be a sequence"); |
714 | return NULL; |
715 | } |
716 | |
717 | exceptions = PySequence_Tuple(exceptions); |
718 | if (!exceptions) { Branch (718:9): [True: 0, False: 10.7k]
|
719 | return NULL; |
720 | } |
721 | |
722 | /* We are now holding a ref to the exceptions tuple */ |
723 | |
724 | Py_ssize_t numexcs = PyTuple_GET_SIZE(exceptions); |
725 | if (numexcs == 0) { Branch (725:9): [True: 1, False: 10.7k]
|
726 | PyErr_SetString( |
727 | PyExc_ValueError, |
728 | "second argument (exceptions) must be a non-empty sequence"); |
729 | goto error; |
730 | } |
731 | |
732 | bool nested_base_exceptions = false; |
733 | for (Py_ssize_t i = 0; i < numexcs; i++17.1k ) { Branch (733:28): [True: 17.1k, False: 10.7k]
|
734 | PyObject *exc = PyTuple_GET_ITEM(exceptions, i); |
735 | if (!exc) { Branch (735:13): [True: 0, False: 17.1k]
|
736 | goto error; |
737 | } |
738 | if (!PyExceptionInstance_Check(exc)) { Branch (738:13): [True: 2, False: 17.1k]
|
739 | PyErr_Format( |
740 | PyExc_ValueError, |
741 | "Item %d of second argument (exceptions) is not an exception", |
742 | i); |
743 | goto error; |
744 | } |
745 | int is_nonbase_exception = PyObject_IsInstance(exc, PyExc_Exception); |
746 | if (is_nonbase_exception < 0) { Branch (746:13): [True: 0, False: 17.1k]
|
747 | goto error; |
748 | } |
749 | else if (is_nonbase_exception == 0) { Branch (749:18): [True: 23, False: 17.1k]
|
750 | nested_base_exceptions = true; |
751 | } |
752 | } |
753 | |
754 | PyTypeObject *cls = type; |
755 | if (cls == PyExc_ExceptionGroup) { Branch (755:9): [True: 10.2k, False: 528]
|
756 | if (nested_base_exceptions) { Branch (756:13): [True: 1, False: 10.2k]
|
757 | PyErr_SetString(PyExc_TypeError, |
758 | "Cannot nest BaseExceptions in an ExceptionGroup"); |
759 | goto error; |
760 | } |
761 | } |
762 | else if (cls == (PyTypeObject*)PyExc_BaseExceptionGroup) { Branch (762:14): [True: 486, False: 42]
|
763 | if (!nested_base_exceptions) { Branch (763:13): [True: 468, False: 18]
|
764 | /* All nested exceptions are Exception subclasses, |
765 | * wrap them in an ExceptionGroup |
766 | */ |
767 | cls = PyExc_ExceptionGroup; |
768 | } |
769 | } |
770 | else { |
771 | /* Do nothing - we don't interfere with subclasses */ |
772 | } |
773 | |
774 | if (!cls) { Branch (774:9): [True: 0, False: 10.7k]
|
775 | /* Don't crash during interpreter shutdown |
776 | * (PyExc_ExceptionGroup may have been cleared) |
777 | */ |
778 | cls = (PyTypeObject*)PyExc_BaseExceptionGroup; |
779 | } |
780 | PyBaseExceptionGroupObject *self = |
781 | _PyBaseExceptionGroupObject_cast(BaseException_new(cls, args, kwds)); |
782 | if (!self) { Branch (782:9): [True: 0, False: 10.7k]
|
783 | goto error; |
784 | } |
785 | |
786 | self->msg = Py_NewRef(message); |
787 | self->excs = exceptions; |
788 | return (PyObject*)self; |
789 | error: |
790 | Py_DECREF(exceptions); |
791 | return NULL; |
792 | } |
793 | |
794 | PyObject * |
795 | _PyExc_CreateExceptionGroup(const char *msg_str, PyObject *excs) |
796 | { |
797 | PyObject *msg = PyUnicode_FromString(msg_str); |
798 | if (!msg) { Branch (798:9): [True: 0, False: 50]
|
799 | return NULL; |
800 | } |
801 | PyObject *args = PyTuple_Pack(2, msg, excs); |
802 | Py_DECREF(msg); |
803 | if (!args) { Branch (803:9): [True: 0, False: 50]
|
804 | return NULL; |
805 | } |
806 | PyObject *result = PyObject_CallObject(PyExc_BaseExceptionGroup, args); |
807 | Py_DECREF(args); |
808 | return result; |
809 | } |
810 | |
811 | static int |
812 | BaseExceptionGroup_init(PyBaseExceptionGroupObject *self, |
813 | PyObject *args, PyObject *kwds) |
814 | { |
815 | if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds)) { |
816 | return -1; |
817 | } |
818 | if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) { Branch (818:9): [True: 0, False: 10.7k]
|
819 | return -1; |
820 | } |
821 | return 0; |
822 | } |
823 | |
824 | static int |
825 | BaseExceptionGroup_clear(PyBaseExceptionGroupObject *self) |
826 | { |
827 | Py_CLEAR(self->msg); |
828 | Py_CLEAR(self->excs); |
829 | return BaseException_clear((PyBaseExceptionObject *)self); |
830 | } |
831 | |
832 | static void |
833 | BaseExceptionGroup_dealloc(PyBaseExceptionGroupObject *self) |
834 | { |
835 | _PyObject_GC_UNTRACK(self); |
836 | BaseExceptionGroup_clear(self); |
837 | Py_TYPE(self)->tp_free((PyObject *)self); |
838 | } |
839 | |
840 | static int |
841 | BaseExceptionGroup_traverse(PyBaseExceptionGroupObject *self, |
842 | visitproc visit, void *arg) |
843 | { |
844 | Py_VISIT(self->msg); |
845 | Py_VISIT(self->excs); |
846 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
847 | } |
848 | |
849 | static PyObject * |
850 | BaseExceptionGroup_str(PyBaseExceptionGroupObject *self) |
851 | { |
852 | assert(self->msg); |
853 | assert(PyUnicode_Check(self->msg)); |
854 | |
855 | assert(PyTuple_CheckExact(self->excs)); |
856 | Py_ssize_t num_excs = PyTuple_Size(self->excs); |
857 | return PyUnicode_FromFormat( |
858 | "%S (%zd sub-exception%s)", |
859 | self->msg, num_excs, num_excs > 1 ? "s"2.06k : ""2.01k ); Branch (859:30): [True: 2.06k, False: 2.01k]
|
860 | } |
861 | |
862 | static PyObject * |
863 | BaseExceptionGroup_derive(PyObject *self_, PyObject *args) |
864 | { |
865 | PyBaseExceptionGroupObject *self = _PyBaseExceptionGroupObject_cast(self_); |
866 | PyObject *excs = NULL; |
867 | if (!PyArg_ParseTuple(args, "O", &excs)) { Branch (867:9): [True: 0, False: 416]
|
868 | return NULL; |
869 | } |
870 | PyObject *init_args = PyTuple_Pack(2, self->msg, excs); |
871 | if (!init_args) { Branch (871:9): [True: 0, False: 416]
|
872 | return NULL; |
873 | } |
874 | PyObject *eg = PyObject_CallObject( |
875 | PyExc_BaseExceptionGroup, init_args); |
876 | Py_DECREF(init_args); |
877 | return eg; |
878 | } |
879 | |
880 | static int |
881 | exceptiongroup_subset( |
882 | PyBaseExceptionGroupObject *_orig, PyObject *excs, PyObject **result) |
883 | { |
884 | /* Sets *result to an ExceptionGroup wrapping excs with metadata from |
885 | * _orig. If excs is empty, sets *result to NULL. |
886 | * Returns 0 on success and -1 on error. |
887 | |
888 | * This function is used by split() to construct the match/rest parts, |
889 | * so excs is the matching or non-matching sub-sequence of orig->excs |
890 | * (this function does not verify that it is a subsequence). |
891 | */ |
892 | PyObject *orig = (PyObject *)_orig; |
893 | |
894 | *result = NULL; |
895 | Py_ssize_t num_excs = PySequence_Size(excs); |
896 | if (num_excs < 0) { Branch (896:9): [True: 0, False: 601]
|
897 | return -1; |
898 | } |
899 | else if (num_excs == 0) { Branch (899:14): [True: 161, False: 440]
|
900 | return 0; |
901 | } |
902 | |
903 | PyObject *eg = PyObject_CallMethod( |
904 | orig, "derive", "(O)", excs); |
905 | if (!eg) { Branch (905:9): [True: 0, False: 440]
|
906 | return -1; |
907 | } |
908 | |
909 | if (!_PyBaseExceptionGroup_Check(eg)) { Branch (909:9): [True: 0, False: 440]
|
910 | PyErr_SetString(PyExc_TypeError, |
911 | "derive must return an instance of BaseExceptionGroup"); |
912 | goto error; |
913 | } |
914 | |
915 | /* Now we hold a reference to the new eg */ |
916 | |
917 | PyObject *tb = PyException_GetTraceback(orig); |
918 | if (tb) { Branch (918:9): [True: 328, False: 112]
|
919 | int res = PyException_SetTraceback(eg, tb); |
920 | Py_DECREF(tb); |
921 | if (res < 0) { Branch (921:13): [True: 0, False: 328]
|
922 | goto error; |
923 | } |
924 | } |
925 | PyException_SetContext(eg, PyException_GetContext(orig)); |
926 | PyException_SetCause(eg, PyException_GetCause(orig)); |
927 | |
928 | if (PyObject_HasAttr(orig, &_Py_ID(__notes__))) { Branch (928:9): [True: 15, False: 425]
|
929 | PyObject *notes = PyObject_GetAttr(orig, &_Py_ID(__notes__)); |
930 | if (notes == NULL) { Branch (930:13): [True: 0, False: 15]
|
931 | goto error; |
932 | } |
933 | if (PySequence_Check(notes)) { Branch (933:13): [True: 13, False: 2]
|
934 | /* Make a copy so the parts have independent notes lists. */ |
935 | PyObject *notes_copy = PySequence_List(notes); |
936 | Py_DECREF(notes); |
937 | if (notes_copy == NULL) { Branch (937:17): [True: 0, False: 13]
|
938 | goto error; |
939 | } |
940 | int res = PyObject_SetAttr(eg, &_Py_ID(__notes__), notes_copy); |
941 | Py_DECREF(notes_copy); |
942 | if (res < 0) { Branch (942:17): [True: 0, False: 13]
|
943 | goto error; |
944 | } |
945 | } |
946 | else { |
947 | /* __notes__ is supposed to be a list, and split() is not a |
948 | * good place to report earlier user errors, so we just ignore |
949 | * notes of non-sequence type. |
950 | */ |
951 | Py_DECREF(notes); |
952 | } |
953 | } |
954 | |
955 | *result = eg; |
956 | return 0; |
957 | error: |
958 | Py_DECREF(eg); |
959 | return -1; |
960 | } |
961 | |
962 | typedef enum { |
963 | /* Exception type or tuple of thereof */ |
964 | EXCEPTION_GROUP_MATCH_BY_TYPE = 0, |
965 | /* A PyFunction returning True for matching exceptions */ |
966 | EXCEPTION_GROUP_MATCH_BY_PREDICATE = 1, |
967 | /* A set of leaf exceptions to include in the result. |
968 | * This matcher type is used internally by the interpreter |
969 | * to construct reraised exceptions. |
970 | */ |
971 | EXCEPTION_GROUP_MATCH_INSTANCES = 2 |
972 | } _exceptiongroup_split_matcher_type; |
973 | |
974 | static int |
975 | get_matcher_type(PyObject *value, |
976 | _exceptiongroup_split_matcher_type *type) |
977 | { |
978 | assert(value); |
979 | |
980 | if (PyFunction_Check(value)) { |
981 | *type = EXCEPTION_GROUP_MATCH_BY_PREDICATE; |
982 | return 0; |
983 | } |
984 | |
985 | if (PyExceptionClass_Check(value)) { |
986 | *type = EXCEPTION_GROUP_MATCH_BY_TYPE; |
987 | return 0; |
988 | } |
989 | |
990 | if (PyTuple_CheckExact(value)) { |
991 | Py_ssize_t n = PyTuple_GET_SIZE(value); |
992 | for (Py_ssize_t i=0; i<n; i++52 ) { Branch (992:30): [True: 54, False: 25]
|
993 | if (!PyExceptionClass_Check(PyTuple_GET_ITEM(value, i))) { |
994 | goto error; |
995 | } |
996 | } |
997 | *type = EXCEPTION_GROUP_MATCH_BY_TYPE; |
998 | return 0; |
999 | } |
1000 | |
1001 | error: |
1002 | PyErr_SetString( |
1003 | PyExc_TypeError, |
1004 | "expected a function, exception type or tuple of exception types"); |
1005 | return -1; |
1006 | } |
1007 | |
1008 | static int |
1009 | exceptiongroup_split_check_match(PyObject *exc, |
1010 | _exceptiongroup_split_matcher_type matcher_type, |
1011 | PyObject *matcher_value) |
1012 | { |
1013 | switch (matcher_type) { Branch (1013:13): [True: 0, False: 3.01k]
|
1014 | case EXCEPTION_GROUP_MATCH_BY_TYPE: { Branch (1014:5): [True: 2.59k, False: 427]
|
1015 | assert(PyExceptionClass_Check(matcher_value) || |
1016 | PyTuple_CheckExact(matcher_value)); |
1017 | return PyErr_GivenExceptionMatches(exc, matcher_value); |
1018 | } |
1019 | case EXCEPTION_GROUP_MATCH_BY_PREDICATE: { Branch (1019:5): [True: 34, False: 2.98k]
|
1020 | assert(PyFunction_Check(matcher_value)); |
1021 | PyObject *exc_matches = PyObject_CallOneArg(matcher_value, exc); |
1022 | if (exc_matches == NULL) { Branch (1022:13): [True: 0, False: 34]
|
1023 | return -1; |
1024 | } |
1025 | int is_true = PyObject_IsTrue(exc_matches); |
1026 | Py_DECREF(exc_matches); |
1027 | return is_true; |
1028 | } |
1029 | case EXCEPTION_GROUP_MATCH_INSTANCES: { Branch (1029:5): [True: 393, False: 2.62k]
|
1030 | assert(PySet_Check(matcher_value)); |
1031 | if (!_PyBaseExceptionGroup_Check(exc)) { Branch (1031:13): [True: 244, False: 149]
|
1032 | return PySet_Contains(matcher_value, exc); |
1033 | } |
1034 | return 0; |
1035 | } |
1036 | } |
1037 | return 0; |
1038 | } |
1039 | |
1040 | typedef struct { |
1041 | PyObject *match; |
1042 | PyObject *rest; |
1043 | } _exceptiongroup_split_result; |
1044 | |
1045 | static int |
1046 | exceptiongroup_split_recursive(PyObject *exc, |
1047 | _exceptiongroup_split_matcher_type matcher_type, |
1048 | PyObject *matcher_value, |
1049 | bool construct_rest, |
1050 | _exceptiongroup_split_result *result) |
1051 | { |
1052 | result->match = NULL; |
1053 | result->rest = NULL; |
1054 | |
1055 | int is_match = exceptiongroup_split_check_match( |
1056 | exc, matcher_type, matcher_value); |
1057 | if (is_match < 0) { Branch (1057:9): [True: 0, False: 3.01k]
|
1058 | return -1; |
1059 | } |
1060 | |
1061 | if (is_match) { Branch (1061:9): [True: 332, False: 2.68k]
|
1062 | /* Full match */ |
1063 | result->match = Py_NewRef(exc); |
1064 | return 0; |
1065 | } |
1066 | else if (!_PyBaseExceptionGroup_Check(exc)) { Branch (1066:14): [True: 348, False: 2.33k]
|
1067 | /* Leaf exception and no match */ |
1068 | if (construct_rest) { Branch (1068:13): [True: 154, False: 194]
|
1069 | result->rest = Py_NewRef(exc); |
1070 | } |
1071 | return 0; |
1072 | } |
1073 | |
1074 | /* Partial match */ |
1075 | |
1076 | PyBaseExceptionGroupObject *eg = _PyBaseExceptionGroupObject_cast(exc); |
1077 | assert(PyTuple_CheckExact(eg->excs)); |
1078 | Py_ssize_t num_excs = PyTuple_Size(eg->excs); |
1079 | if (num_excs < 0) { Branch (1079:9): [True: 0, False: 2.33k]
|
1080 | return -1; |
1081 | } |
1082 | assert(num_excs > 0); /* checked in constructor, and excs is read-only */ |
1083 | |
1084 | int retval = -1; |
1085 | PyObject *match_list = PyList_New(0); |
1086 | if (!match_list) { Branch (1086:9): [True: 0, False: 2.33k]
|
1087 | return -1; |
1088 | } |
1089 | |
1090 | PyObject *rest_list = NULL; |
1091 | if (construct_rest) { Branch (1091:9): [True: 1.17k, False: 1.16k]
|
1092 | rest_list = PyList_New(0); |
1093 | if (!rest_list) { Branch (1093:13): [True: 0, False: 1.17k]
|
1094 | goto done; |
1095 | } |
1096 | } |
1097 | /* recursive calls */ |
1098 | for (Py_ssize_t i = 0; 2.33k i < num_excs; i++805 ) { Branch (1098:28): [True: 2.74k, False: 399]
|
1099 | PyObject *e = PyTuple_GET_ITEM(eg->excs, i); |
1100 | _exceptiongroup_split_result rec_result; |
1101 | if (_Py_EnterRecursiveCall(" in exceptiongroup_split_recursive")) { Branch (1101:13): [True: 2, False: 2.74k]
|
1102 | goto done; |
1103 | } |
1104 | if (exceptiongroup_split_recursive( Branch (1104:13): [True: 1.93k, False: 805]
|
1105 | e, matcher_type, matcher_value, |
1106 | construct_rest, &rec_result) < 0) { |
1107 | assert(!rec_result.match); |
1108 | assert(!rec_result.rest); |
1109 | _Py_LeaveRecursiveCall(); |
1110 | goto done; |
1111 | } |
1112 | _Py_LeaveRecursiveCall(); |
1113 | if (rec_result.match) { Branch (1113:13): [True: 418, False: 387]
|
1114 | assert(PyList_CheckExact(match_list)); |
1115 | if (PyList_Append(match_list, rec_result.match) < 0) { Branch (1115:17): [True: 0, False: 418]
|
1116 | Py_DECREF(rec_result.match); |
1117 | goto done; |
1118 | } |
1119 | Py_DECREF(rec_result.match); |
1120 | } |
1121 | if (rec_result.rest) { Branch (1121:13): [True: 204, False: 601]
|
1122 | assert(construct_rest); |
1123 | assert(PyList_CheckExact(rest_list)); |
1124 | if (PyList_Append(rest_list, rec_result.rest) < 0) { Branch (1124:17): [True: 0, False: 204]
|
1125 | Py_DECREF(rec_result.rest); |
1126 | goto done; |
1127 | } |
1128 | Py_DECREF(rec_result.rest); |
1129 | } |
1130 | } |
1131 | |
1132 | /* construct result */ |
1133 | if (exceptiongroup_subset(eg, match_list, &result->match) < 0) { Branch (1133:9): [True: 0, False: 399]
|
1134 | goto done; |
1135 | } |
1136 | |
1137 | if (construct_rest) { Branch (1137:9): [True: 202, False: 197]
|
1138 | assert(PyList_CheckExact(rest_list)); |
1139 | if (exceptiongroup_subset(eg, rest_list, &result->rest) < 0) { Branch (1139:13): [True: 0, False: 202]
|
1140 | Py_CLEAR(result->match); |
1141 | goto done; |
1142 | } |
1143 | } |
1144 | retval = 0; |
1145 | done: |
1146 | Py_DECREF(match_list); |
1147 | Py_XDECREF(rest_list); |
1148 | if (retval < 0) { Branch (1148:9): [True: 1.93k, False: 399]
|
1149 | Py_CLEAR(result->match); |
1150 | Py_CLEAR(result->rest); |
1151 | } |
1152 | return retval; |
1153 | } |
1154 | |
1155 | static PyObject * |
1156 | BaseExceptionGroup_split(PyObject *self, PyObject *args) |
1157 | { |
1158 | PyObject *matcher_value = NULL; |
1159 | if (!PyArg_UnpackTuple(args, "split", 1, 1, &matcher_value)) { Branch (1159:9): [True: 0, False: 145]
|
1160 | return NULL; |
1161 | } |
1162 | |
1163 | _exceptiongroup_split_matcher_type matcher_type; |
1164 | if (get_matcher_type(matcher_value, &matcher_type) < 0) { Branch (1164:9): [True: 4, False: 141]
|
1165 | return NULL; |
1166 | } |
1167 | |
1168 | _exceptiongroup_split_result split_result; |
1169 | bool construct_rest = true; |
1170 | if (exceptiongroup_split_recursive( Branch (1170:9): [True: 1, False: 140]
|
1171 | self, matcher_type, matcher_value, |
1172 | construct_rest, &split_result) < 0) { |
1173 | return NULL; |
1174 | } |
1175 | |
1176 | PyObject *result = PyTuple_Pack( |
1177 | 2, |
1178 | split_result.match ? split_result.match124 : Py_None16 , Branch (1178:13): [True: 124, False: 16]
|
1179 | split_result.rest ? split_result.rest96 : Py_None44 ); Branch (1179:13): [True: 96, False: 44]
|
1180 | |
1181 | Py_XDECREF(split_result.match); |
1182 | Py_XDECREF(split_result.rest); |
1183 | return result; |
1184 | } |
1185 | |
1186 | static PyObject * |
1187 | BaseExceptionGroup_subgroup(PyObject *self, PyObject *args) |
1188 | { |
1189 | PyObject *matcher_value = NULL; |
1190 | if (!PyArg_UnpackTuple(args, "subgroup", 1, 1, &matcher_value)) { Branch (1190:9): [True: 0, False: 39]
|
1191 | return NULL; |
1192 | } |
1193 | |
1194 | _exceptiongroup_split_matcher_type matcher_type; |
1195 | if (get_matcher_type(matcher_value, &matcher_type) < 0) { Branch (1195:9): [True: 4, False: 35]
|
1196 | return NULL; |
1197 | } |
1198 | |
1199 | _exceptiongroup_split_result split_result; |
1200 | bool construct_rest = false; |
1201 | if (exceptiongroup_split_recursive( Branch (1201:9): [True: 1, False: 34]
|
1202 | self, matcher_type, matcher_value, |
1203 | construct_rest, &split_result) < 0) { |
1204 | return NULL; |
1205 | } |
1206 | |
1207 | PyObject *result = Py_NewRef( |
1208 | split_result.match ? split_result.match : Py_None); |
1209 | |
1210 | Py_XDECREF(split_result.match); |
1211 | assert(!split_result.rest); |
1212 | return result; |
1213 | } |
1214 | |
1215 | static int |
1216 | collect_exception_group_leaves(PyObject *exc, PyObject *leaves) |
1217 | { |
1218 | if (Py_IsNone(exc)) { |
1219 | return 0; |
1220 | } |
1221 | |
1222 | assert(PyExceptionInstance_Check(exc)); |
1223 | assert(PySet_Check(leaves)); |
1224 | |
1225 | /* Add all leaf exceptions in exc to the leaves set */ |
1226 | |
1227 | if (!_PyBaseExceptionGroup_Check(exc)) { Branch (1227:9): [True: 94, False: 101]
|
1228 | if (PySet_Add(leaves, exc) < 0) { Branch (1228:13): [True: 0, False: 94]
|
1229 | return -1; |
1230 | } |
1231 | return 0; |
1232 | } |
1233 | PyBaseExceptionGroupObject *eg = _PyBaseExceptionGroupObject_cast(exc); |
1234 | Py_ssize_t num_excs = PyTuple_GET_SIZE(eg->excs); |
1235 | /* recursive calls */ |
1236 | for (Py_ssize_t i = 0; i < num_excs; i++131 ) { Branch (1236:28): [True: 131, False: 101]
|
1237 | PyObject *e = PyTuple_GET_ITEM(eg->excs, i); |
1238 | if (_Py_EnterRecursiveCall(" in collect_exception_group_leaves")) { Branch (1238:13): [True: 0, False: 131]
|
1239 | return -1; |
1240 | } |
1241 | int res = collect_exception_group_leaves(e, leaves); |
1242 | _Py_LeaveRecursiveCall(); |
1243 | if (res < 0) { Branch (1243:13): [True: 0, False: 131]
|
1244 | return -1; |
1245 | } |
1246 | } |
1247 | return 0; |
1248 | } |
1249 | |
1250 | /* This function is used by the interpreter to construct reraised |
1251 | * exception groups. It takes an exception group eg and a list |
1252 | * of exception groups keep and returns the sub-exception group |
1253 | * of eg which contains all leaf exceptions that are contained |
1254 | * in any exception group in keep. |
1255 | */ |
1256 | static PyObject * |
1257 | exception_group_projection(PyObject *eg, PyObject *keep) |
1258 | { |
1259 | assert(_PyBaseExceptionGroup_Check(eg)); |
1260 | assert(PyList_CheckExact(keep)); |
1261 | |
1262 | PyObject *leaves = PySet_New(NULL); |
1263 | if (!leaves) { Branch (1263:9): [True: 0, False: 100]
|
1264 | return NULL; |
1265 | } |
1266 | |
1267 | Py_ssize_t n = PyList_GET_SIZE(keep); |
1268 | for (Py_ssize_t i = 0; i < n; i++64 ) { Branch (1268:28): [True: 64, False: 100]
|
1269 | PyObject *e = PyList_GET_ITEM(keep, i); |
1270 | assert(e != NULL); |
1271 | assert(_PyBaseExceptionGroup_Check(e)); |
1272 | if (collect_exception_group_leaves(e, leaves) < 0) { Branch (1272:13): [True: 0, False: 64]
|
1273 | Py_DECREF(leaves); |
1274 | return NULL; |
1275 | } |
1276 | } |
1277 | |
1278 | _exceptiongroup_split_result split_result; |
1279 | bool construct_rest = false; |
1280 | int err = exceptiongroup_split_recursive( |
1281 | eg, EXCEPTION_GROUP_MATCH_INSTANCES, leaves, |
1282 | construct_rest, &split_result); |
1283 | Py_DECREF(leaves); |
1284 | if (err < 0) { Branch (1284:9): [True: 0, False: 100]
|
1285 | return NULL; |
1286 | } |
1287 | |
1288 | PyObject *result = split_result.match ? Branch (1288:24): [True: 57, False: 43]
|
1289 | split_result.match : Py_NewRef43 (Py_None); |
1290 | assert(split_result.rest == NULL); |
1291 | return result; |
1292 | } |
1293 | |
1294 | static bool |
1295 | is_same_exception_metadata(PyObject *exc1, PyObject *exc2) |
1296 | { |
1297 | assert(PyExceptionInstance_Check(exc1)); |
1298 | assert(PyExceptionInstance_Check(exc2)); |
1299 | |
1300 | PyBaseExceptionObject *e1 = (PyBaseExceptionObject *)exc1; |
1301 | PyBaseExceptionObject *e2 = (PyBaseExceptionObject *)exc2; |
1302 | |
1303 | return (e1->notes == e2->notes && Branch (1303:13): [True: 80, False: 0]
|
1304 | e1->traceback == e2->traceback && Branch (1304:13): [True: 64, False: 16]
|
1305 | e1->cause == e2->cause64 && Branch (1305:13): [True: 64, False: 0]
|
1306 | e1->context == e2->context64 ); Branch (1306:13): [True: 64, False: 0]
|
1307 | } |
1308 | |
1309 | /* |
1310 | This function is used by the interpreter to calculate |
1311 | the exception group to be raised at the end of a |
1312 | try-except* construct. |
1313 | |
1314 | orig: the original except that was caught. |
1315 | excs: a list of exceptions that were raised/reraised |
1316 | in the except* clauses. |
1317 | |
1318 | Calculates an exception group to raise. It contains |
1319 | all exceptions in excs, where those that were reraised |
1320 | have same nesting structure as in orig, and those that |
1321 | were raised (if any) are added as siblings in a new EG. |
1322 | |
1323 | Returns NULL and sets an exception on failure. |
1324 | */ |
1325 | PyObject * |
1326 | _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs) |
1327 | { |
1328 | assert(PyExceptionInstance_Check(orig)); |
1329 | assert(PyList_Check(excs)); |
1330 | |
1331 | Py_ssize_t numexcs = PyList_GET_SIZE(excs); |
1332 | |
1333 | if (numexcs == 0) { Branch (1333:9): [True: 0, False: 150]
|
1334 | return Py_NewRef(Py_None); |
1335 | } |
1336 | |
1337 | if (!_PyBaseExceptionGroup_Check(orig)) { Branch (1337:9): [True: 50, False: 100]
|
1338 | /* a naked exception was caught and wrapped. Only one except* clause |
1339 | * could have executed,so there is at most one exception to raise. |
1340 | */ |
1341 | |
1342 | assert(numexcs == 1 || (numexcs == 2 && PyList_GET_ITEM(excs, 1) == Py_None)); |
1343 | |
1344 | PyObject *e = PyList_GET_ITEM(excs, 0); |
1345 | assert(e != NULL); |
1346 | return Py_NewRef(e); |
1347 | } |
1348 | |
1349 | PyObject *raised_list = PyList_New(0); |
1350 | if (raised_list == NULL) { Branch (1350:9): [True: 0, False: 100]
|
1351 | return NULL; |
1352 | } |
1353 | PyObject* reraised_list = PyList_New(0); |
1354 | if (reraised_list == NULL) { Branch (1354:9): [True: 0, False: 100]
|
1355 | Py_DECREF(raised_list); |
1356 | return NULL; |
1357 | } |
1358 | |
1359 | /* Now we are holding refs to raised_list and reraised_list */ |
1360 | |
1361 | PyObject *result = NULL; |
1362 | |
1363 | /* Split excs into raised and reraised by comparing metadata with orig */ |
1364 | for (Py_ssize_t i = 0; i < numexcs; i++128 ) { Branch (1364:28): [True: 128, False: 100]
|
1365 | PyObject *e = PyList_GET_ITEM(excs, i); |
1366 | assert(e != NULL); |
1367 | if (Py_IsNone(e)) { |
1368 | continue; |
1369 | } |
1370 | bool is_reraise = is_same_exception_metadata(e, orig); |
1371 | PyObject *append_list = is_reraise ? reraised_list64 : raised_list16 ; Branch (1371:33): [True: 64, False: 16]
|
1372 | if (PyList_Append(append_list, e) < 0) { Branch (1372:13): [True: 0, False: 80]
|
1373 | goto done; |
1374 | } |
1375 | } |
1376 | |
1377 | PyObject *reraised_eg = exception_group_projection(orig, reraised_list); |
1378 | if (reraised_eg == NULL) { Branch (1378:9): [True: 0, False: 100]
|
1379 | goto done; |
1380 | } |
1381 | |
1382 | if (!Py_IsNone(reraised_eg)) { Branch (1382:9): [True: 57, False: 43]
|
1383 | assert(is_same_exception_metadata(reraised_eg, orig)); |
1384 | } |
1385 | Py_ssize_t num_raised = PyList_GET_SIZE(raised_list); |
1386 | if (num_raised == 0) { Branch (1386:9): [True: 88, False: 12]
|
1387 | result = reraised_eg; |
1388 | } |
1389 | else if (num_raised > 0) { Branch (1389:14): [True: 12, False: 0]
|
1390 | int res = 0; |
1391 | if (!Py_IsNone(reraised_eg)) { Branch (1391:13): [True: 4, False: 8]
|
1392 | res = PyList_Append(raised_list, reraised_eg); |
1393 | } |
1394 | Py_DECREF(reraised_eg); |
1395 | if (res < 0) { Branch (1395:13): [True: 0, False: 12]
|
1396 | goto done; |
1397 | } |
1398 | result = _PyExc_CreateExceptionGroup("", raised_list); |
1399 | if (result == NULL) { Branch (1399:13): [True: 0, False: 12]
|
1400 | goto done; |
1401 | } |
1402 | } |
1403 | |
1404 | done: |
1405 | Py_XDECREF(raised_list); |
1406 | Py_XDECREF(reraised_list); |
1407 | return result; |
1408 | } |
1409 | |
1410 | static PyMemberDef BaseExceptionGroup_members[] = { |
1411 | {"message", T_OBJECT, offsetof(PyBaseExceptionGroupObject, msg), READONLY, |
1412 | PyDoc_STR("exception message")}, |
1413 | {"exceptions", T_OBJECT, offsetof(PyBaseExceptionGroupObject, excs), READONLY, |
1414 | PyDoc_STR("nested exceptions")}, |
1415 | {NULL} /* Sentinel */ |
1416 | }; |
1417 | |
1418 | static PyMethodDef BaseExceptionGroup_methods[] = { |
1419 | {"__class_getitem__", (PyCFunction)Py_GenericAlias, |
1420 | METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, |
1421 | {"derive", (PyCFunction)BaseExceptionGroup_derive, METH_VARARGS}, |
1422 | {"split", (PyCFunction)BaseExceptionGroup_split, METH_VARARGS}, |
1423 | {"subgroup", (PyCFunction)BaseExceptionGroup_subgroup, METH_VARARGS}, |
1424 | {NULL} |
1425 | }; |
1426 | |
1427 | ComplexExtendsException(PyExc_BaseException, BaseExceptionGroup, |
1428 | BaseExceptionGroup, BaseExceptionGroup_new /* new */, |
1429 | BaseExceptionGroup_methods, BaseExceptionGroup_members, |
1430 | 0 /* getset */, BaseExceptionGroup_str, |
1431 | "A combination of multiple unrelated exceptions."); |
1432 | |
1433 | /* |
1434 | * ExceptionGroup extends BaseExceptionGroup, Exception |
1435 | */ |
1436 | static PyObject* |
1437 | create_exception_group_class(void) { |
1438 | struct _Py_exc_state *state = get_exc_state(); |
1439 | |
1440 | PyObject *bases = PyTuple_Pack( |
1441 | 2, PyExc_BaseExceptionGroup, PyExc_Exception); |
1442 | if (bases == NULL) { Branch (1442:9): [True: 0, False: 278]
|
1443 | return NULL; |
1444 | } |
1445 | |
1446 | assert(!state->PyExc_ExceptionGroup); |
1447 | state->PyExc_ExceptionGroup = PyErr_NewException( |
1448 | "builtins.ExceptionGroup", bases, NULL); |
1449 | |
1450 | Py_DECREF(bases); |
1451 | return state->PyExc_ExceptionGroup; |
1452 | } |
1453 | |
1454 | /* |
1455 | * KeyboardInterrupt extends BaseException |
1456 | */ |
1457 | SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt, |
1458 | "Program interrupted by user."); |
1459 | |
1460 | |
1461 | /* |
1462 | * ImportError extends Exception |
1463 | */ |
1464 | |
1465 | static int |
1466 | ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds) |
1467 | { |
1468 | static char *kwlist[] = {"name", "path", 0}; |
1469 | PyObject *empty_tuple; |
1470 | PyObject *msg = NULL; |
1471 | PyObject *name = NULL; |
1472 | PyObject *path = NULL; |
1473 | |
1474 | if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) Branch (1474:9): [True: 0, False: 5.32k]
|
1475 | return -1; |
1476 | |
1477 | empty_tuple = PyTuple_New(0); |
1478 | if (!empty_tuple) Branch (1478:9): [True: 0, False: 5.32k]
|
1479 | return -1; |
1480 | if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OO:ImportError", kwlist, Branch (1480:9): [True: 6, False: 5.31k]
|
1481 | &name, &path)) { |
1482 | Py_DECREF(empty_tuple); |
1483 | return -1; |
1484 | } |
1485 | Py_DECREF(empty_tuple); |
1486 | |
1487 | Py_XINCREF(name); |
1488 | Py_XSETREF(self->name, name); |
1489 | |
1490 | Py_XINCREF(path); |
1491 | Py_XSETREF(self->path, path); |
1492 | |
1493 | if (PyTuple_GET_SIZE(args) == 1) { Branch (1493:9): [True: 5.25k, False: 63]
|
1494 | msg = PyTuple_GET_ITEM(args, 0); |
1495 | Py_INCREF(msg); |
1496 | } |
1497 | Py_XSETREF(self->msg, msg); |
1498 | |
1499 | return 0; |
1500 | } |
1501 | |
1502 | static int |
1503 | ImportError_clear(PyImportErrorObject *self) |
1504 | { |
1505 | Py_CLEAR(self->msg); |
1506 | Py_CLEAR(self->name); |
1507 | Py_CLEAR(self->path); |
1508 | return BaseException_clear((PyBaseExceptionObject *)self); |
1509 | } |
1510 | |
1511 | static void |
1512 | ImportError_dealloc(PyImportErrorObject *self) |
1513 | { |
1514 | _PyObject_GC_UNTRACK(self); |
1515 | ImportError_clear(self); |
1516 | Py_TYPE(self)->tp_free((PyObject *)self); |
1517 | } |
1518 | |
1519 | static int |
1520 | ImportError_traverse(PyImportErrorObject *self, visitproc visit, void *arg) |
1521 | { |
1522 | Py_VISIT(self->msg); |
1523 | Py_VISIT(self->name); |
1524 | Py_VISIT(self->path); |
1525 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
1526 | } |
1527 | |
1528 | static PyObject * |
1529 | ImportError_str(PyImportErrorObject *self) |
1530 | { |
1531 | if (self->msg && PyUnicode_CheckExact(self->msg)) { Branch (1531:9): [True: 82, False: 0]
|
1532 | Py_INCREF(self->msg); |
1533 | return self->msg; |
1534 | } |
1535 | else { |
1536 | return BaseException_str((PyBaseExceptionObject *)self); |
1537 | } |
1538 | } |
1539 | |
1540 | static PyObject * |
1541 | ImportError_getstate(PyImportErrorObject *self) |
1542 | { |
1543 | PyObject *dict = ((PyBaseExceptionObject *)self)->dict; |
1544 | if (self->name || self->path22 ) { Branch (1544:9): [True: 16, False: 22]
Branch (1544:23): [True: 8, False: 14]
|
1545 | dict = dict ? PyDict_Copy(dict)0 : PyDict_New(); Branch (1545:16): [True: 0, False: 24]
|
1546 | if (dict == NULL) Branch (1546:13): [True: 0, False: 24]
|
1547 | return NULL; |
1548 | if (self->name && PyDict_SetItem(dict, &16 _Py_ID16 (name), self->name) < 0) { Branch (1548:13): [True: 16, False: 8]
Branch (1548:27): [True: 0, False: 16]
|
1549 | Py_DECREF(dict); |
1550 | return NULL; |
1551 | } |
1552 | if (self->path && PyDict_SetItem(dict, &16 _Py_ID16 (path), self->path) < 0) { Branch (1552:13): [True: 16, False: 8]
Branch (1552:27): [True: 0, False: 16]
|
1553 | Py_DECREF(dict); |
1554 | return NULL; |
1555 | } |
1556 | return dict; |
1557 | } |
1558 | else if (dict) { Branch (1558:14): [True: 0, False: 14]
|
1559 | Py_INCREF(dict); |
1560 | return dict; |
1561 | } |
1562 | else { |
1563 | Py_RETURN_NONE; |
1564 | } |
1565 | } |
1566 | |
1567 | /* Pickling support */ |
1568 | static PyObject * |
1569 | ImportError_reduce(PyImportErrorObject *self, PyObject *Py_UNUSED(ignored)) |
1570 | { |
1571 | PyObject *res; |
1572 | PyObject *args; |
1573 | PyObject *state = ImportError_getstate(self); |
1574 | if (state == NULL) Branch (1574:9): [True: 0, False: 38]
|
1575 | return NULL; |
1576 | args = ((PyBaseExceptionObject *)self)->args; |
1577 | if (state == Py_None) Branch (1577:9): [True: 14, False: 24]
|
1578 | res = PyTuple_Pack(2, Py_TYPE(self), args); |
1579 | else |
1580 | res = PyTuple_Pack(3, Py_TYPE(self), args, state); |
1581 | Py_DECREF(state); |
1582 | return res; |
1583 | } |
1584 | |
1585 | static PyMemberDef ImportError_members[] = { |
1586 | {"msg", T_OBJECT, offsetof(PyImportErrorObject, msg), 0, |
1587 | PyDoc_STR("exception message")}, |
1588 | {"name", T_OBJECT, offsetof(PyImportErrorObject, name), 0, |
1589 | PyDoc_STR("module name")}, |
1590 | {"path", T_OBJECT, offsetof(PyImportErrorObject, path), 0, |
1591 | PyDoc_STR("module path")}, |
1592 | {NULL} /* Sentinel */ |
1593 | }; |
1594 | |
1595 | static PyMethodDef ImportError_methods[] = { |
1596 | {"__reduce__", (PyCFunction)ImportError_reduce, METH_NOARGS}, |
1597 | {NULL} |
1598 | }; |
1599 | |
1600 | ComplexExtendsException(PyExc_Exception, ImportError, |
1601 | ImportError, 0 /* new */, |
1602 | ImportError_methods, ImportError_members, |
1603 | 0 /* getset */, ImportError_str, |
1604 | "Import can't find module, or can't find name in " |
1605 | "module."); |
1606 | |
1607 | /* |
1608 | * ModuleNotFoundError extends ImportError |
1609 | */ |
1610 | |
1611 | MiddlingExtendsException(PyExc_ImportError, ModuleNotFoundError, ImportError, |
1612 | "Module not found."); |
1613 | |
1614 | /* |
1615 | * OSError extends Exception |
1616 | */ |
1617 | |
1618 | #ifdef MS_WINDOWS |
1619 | #include "errmap.h" |
1620 | #endif |
1621 | |
1622 | /* Where a function has a single filename, such as open() or some |
1623 | * of the os module functions, PyErr_SetFromErrnoWithFilename() is |
1624 | * called, giving a third argument which is the filename. But, so |
1625 | * that old code using in-place unpacking doesn't break, e.g.: |
1626 | * |
1627 | * except OSError, (errno, strerror): |
1628 | * |
1629 | * we hack args so that it only contains two items. This also |
1630 | * means we need our own __str__() which prints out the filename |
1631 | * when it was supplied. |
1632 | * |
1633 | * (If a function has two filenames, such as rename(), symlink(), |
1634 | * or copy(), PyErr_SetFromErrnoWithFilenameObjects() is called, |
1635 | * which allows passing in a second filename.) |
1636 | */ |
1637 | |
1638 | /* This function doesn't cleanup on error, the caller should */ |
1639 | static int |
1640 | oserror_parse_args(PyObject **p_args, |
1641 | PyObject **myerrno, PyObject **strerror, |
1642 | PyObject **filename, PyObject **filename2 |
1643 | #ifdef MS_WINDOWS |
1644 | , PyObject **winerror |
1645 | #endif |
1646 | ) |
1647 | { |
1648 | Py_ssize_t nargs; |
1649 | PyObject *args = *p_args; |
1650 | #ifndef MS_WINDOWS |
1651 | /* |
1652 | * ignored on non-Windows platforms, |
1653 | * but parsed so OSError has a consistent signature |
1654 | */ |
1655 | PyObject *_winerror = NULL; |
1656 | PyObject **winerror = &_winerror; |
1657 | #endif /* MS_WINDOWS */ |
1658 | |
1659 | nargs = PyTuple_GET_SIZE(args); |
1660 | |
1661 | if (nargs >= 2 && nargs <= 5177k ) { Branch (1661:9): [True: 177k, False: 2.11k]
Branch (1661:23): [True: 177k, False: 0]
|
1662 | if (!PyArg_UnpackTuple(args, "OSError", 2, 5, Branch (1662:13): [True: 0, False: 177k]
|
1663 | myerrno, strerror, |
1664 | filename, winerror, filename2)) |
1665 | return -1; |
1666 | #ifdef MS_WINDOWS |
1667 | if (*winerror && PyLong_Check(*winerror)) { |
1668 | long errcode, winerrcode; |
1669 | PyObject *newargs; |
1670 | Py_ssize_t i; |
1671 | |
1672 | winerrcode = PyLong_AsLong(*winerror); |
1673 | if (winerrcode == -1 && PyErr_Occurred()) |
1674 | return -1; |
1675 | errcode = winerror_to_errno(winerrcode); |
1676 | *myerrno = PyLong_FromLong(errcode); |
1677 | if (!*myerrno) |
1678 | return -1; |
1679 | newargs = PyTuple_New(nargs); |
1680 | if (!newargs) |
1681 | return -1; |
1682 | PyTuple_SET_ITEM(newargs, 0, *myerrno); |
1683 | for (i = 1; i < nargs; i++) { |
1684 | PyObject *val = PyTuple_GET_ITEM(args, i); |
1685 | Py_INCREF(val); |
1686 | PyTuple_SET_ITEM(newargs, i, val); |
1687 | } |
1688 | Py_DECREF(args); |
1689 | args = *p_args = newargs; |
1690 | } |
1691 | #endif /* MS_WINDOWS */ |
1692 | } |
1693 | |
1694 | return 0; |
1695 | } |
1696 | |
1697 | static int |
1698 | oserror_init(PyOSErrorObject *self, PyObject **p_args, |
1699 | PyObject *myerrno, PyObject *strerror, |
1700 | PyObject *filename, PyObject *filename2 |
1701 | #ifdef MS_WINDOWS |
1702 | , PyObject *winerror |
1703 | #endif |
1704 | ) |
1705 | { |
1706 | PyObject *args = *p_args; |
1707 | Py_ssize_t nargs = PyTuple_GET_SIZE(args); |
1708 | |
1709 | /* self->filename will remain Py_None otherwise */ |
1710 | if (filename && filename != 150k Py_None150k ) { Branch (1710:9): [True: 150k, False: 28.8k]
Branch (1710:21): [True: 150k, False: 9]
|
1711 | if (Py_IS_TYPE(self, (PyTypeObject *) PyExc_BlockingIOError) && |
1712 | PyNumber_Check(filename)35 ) { Branch (1712:13): [True: 32, False: 3]
|
1713 | /* BlockingIOError's 3rd argument can be the number of |
1714 | * characters written. |
1715 | */ |
1716 | self->written = PyNumber_AsSsize_t(filename, PyExc_ValueError); |
1717 | if (self->written == -1 && PyErr_Occurred()0 ) Branch (1717:17): [True: 0, False: 32]
Branch (1717:40): [True: 0, False: 0]
|
1718 | return -1; |
1719 | } |
1720 | else { |
1721 | Py_INCREF(filename); |
1722 | self->filename = filename; |
1723 | |
1724 | if (filename2 && filename2 != 135 Py_None135 ) { Branch (1724:17): [True: 135, False: 150k]
Branch (1724:30): [True: 135, False: 0]
|
1725 | Py_INCREF(filename2); |
1726 | self->filename2 = filename2; |
1727 | } |
1728 | |
1729 | if (nargs >= 2 && nargs <= 5) { Branch (1729:17): [True: 150k, False: 0]
Branch (1729:31): [True: 150k, False: 0]
|
1730 | /* filename, filename2, and winerror are removed from the args tuple |
1731 | (for compatibility purposes, see test_exceptions.py) */ |
1732 | PyObject *subslice = PyTuple_GetSlice(args, 0, 2); |
1733 | if (!subslice) Branch (1733:21): [True: 0, False: 150k]
|
1734 | return -1; |
1735 | |
1736 | Py_DECREF(args); /* replacing args */ |
1737 | *p_args = args = subslice; |
1738 | } |
1739 | } |
1740 | } |
1741 | Py_XINCREF(myerrno); |
1742 | self->myerrno = myerrno; |
1743 | |
1744 | Py_XINCREF(strerror); |
1745 | self->strerror = strerror; |
1746 | |
1747 | #ifdef MS_WINDOWS |
1748 | Py_XINCREF(winerror); |
1749 | self->winerror = winerror; |
1750 | #endif |
1751 | |
1752 | /* Steals the reference to args */ |
1753 | Py_XSETREF(self->args, args); |
1754 | *p_args = args = NULL; |
1755 | |
1756 | return 0; |
1757 | } |
1758 | |
1759 | static PyObject * |
1760 | OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds); |
1761 | static int |
1762 | OSError_init(PyOSErrorObject *self, PyObject *args, PyObject *kwds); |
1763 | |
1764 | static int |
1765 | oserror_use_init(PyTypeObject *type) |
1766 | { |
1767 | /* When __init__ is defined in an OSError subclass, we want any |
1768 | extraneous argument to __new__ to be ignored. The only reasonable |
1769 | solution, given __new__ takes a variable number of arguments, |
1770 | is to defer arg parsing and initialization to __init__. |
1771 | |
1772 | But when __new__ is overridden as well, it should call our __new__ |
1773 | with the right arguments. |
1774 | |
1775 | (see http://bugs.python.org/issue12555#msg148829 ) |
1776 | */ |
1777 | if (type->tp_init != (initproc) OSError_init && Branch (1777:9): [True: 155, False: 537k]
|
1778 | type->tp_new == (newfunc) OSError_new155 ) { Branch (1778:9): [True: 149, False: 6]
|
1779 | assert((PyObject *) type != PyExc_OSError); |
1780 | return 1; |
1781 | } |
1782 | return 0; |
1783 | } |
1784 | |
1785 | static PyObject * |
1786 | OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
1787 | { |
1788 | PyOSErrorObject *self = NULL; |
1789 | PyObject *myerrno = NULL, *strerror = NULL; |
1790 | PyObject *filename = NULL, *filename2 = NULL; |
1791 | #ifdef MS_WINDOWS |
1792 | PyObject *winerror = NULL; |
1793 | #endif |
1794 | |
1795 | Py_INCREF(args); |
1796 | |
1797 | if (!oserror_use_init(type)) { Branch (1797:9): [True: 179k, False: 71]
|
1798 | if (!_PyArg_NoKeywords(type->tp_name, kwds)) |
1799 | goto error; |
1800 | |
1801 | if (oserror_parse_args(&args, &myerrno, &strerror, Branch (1801:13): [True: 0, False: 179k]
|
1802 | &filename, &filename2 |
1803 | #ifdef MS_WINDOWS |
1804 | , &winerror |
1805 | #endif |
1806 | )) |
1807 | goto error; |
1808 | |
1809 | struct _Py_exc_state *state = get_exc_state(); |
1810 | if (myerrno && PyLong_Check(myerrno) && Branch (1810:13): [True: 177k, False: 2.10k]
|
1811 | state->errnomap177k && (PyObject *) type == PyExc_OSError177k ) { Branch (1811:13): [True: 177k, False: 0]
Branch (1811:32): [True: 151k, False: 25.1k]
|
1812 | PyObject *newtype; |
1813 | newtype = PyDict_GetItemWithError(state->errnomap, myerrno); |
1814 | if (newtype) { Branch (1814:17): [True: 140k, False: 11.5k]
|
1815 | type = _PyType_CAST(newtype); |
1816 | } |
1817 | else if (PyErr_Occurred()) Branch (1817:22): [True: 0, False: 11.5k]
|
1818 | goto error; |
1819 | } |
1820 | } |
1821 | |
1822 | self = (PyOSErrorObject *) type->tp_alloc(type, 0); |
1823 | if (!self) Branch (1823:9): [True: 0, False: 179k]
|
1824 | goto error; |
1825 | |
1826 | self->dict = NULL; |
1827 | self->traceback = self->cause = self->context = NULL; |
1828 | self->written = -1; |
1829 | |
1830 | if (!oserror_use_init(type)) { Branch (1830:9): [True: 179k, False: 71]
|
1831 | if (oserror_init(self, &args, myerrno, strerror, filename, filename2 Branch (1831:13): [True: 0, False: 179k]
|
1832 | #ifdef MS_WINDOWS |
1833 | , winerror |
1834 | #endif |
1835 | )) |
1836 | goto error; |
1837 | } |
1838 | else { |
1839 | self->args = PyTuple_New(0); |
1840 | if (self->args == NULL) Branch (1840:13): [True: 0, False: 71]
|
1841 | goto error; |
1842 | } |
1843 | |
1844 | Py_XDECREF(args); |
1845 | return (PyObject *) self; |
1846 | |
1847 | error: |
1848 | Py_XDECREF(args); |
1849 | Py_XDECREF(self); |
1850 | return NULL; |
1851 | } |
1852 | |
1853 | static int |
1854 | OSError_init(PyOSErrorObject *self, PyObject *args, PyObject *kwds) |
1855 | { |
1856 | PyObject *myerrno = NULL, *strerror = NULL; |
1857 | PyObject *filename = NULL, *filename2 = NULL; |
1858 | #ifdef MS_WINDOWS |
1859 | PyObject *winerror = NULL; |
1860 | #endif |
1861 | |
1862 | if (!oserror_use_init(Py_TYPE(self))) Branch (1862:9): [True: 179k, False: 7]
|
1863 | /* Everything already done in OSError_new */ |
1864 | return 0; |
1865 | |
1866 | if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds)) |
1867 | return -1; |
1868 | |
1869 | Py_INCREF(args); |
1870 | if (oserror_parse_args(&args, &myerrno, &strerror, &filename, &filename2 Branch (1870:9): [True: 0, False: 7]
|
1871 | #ifdef MS_WINDOWS |
1872 | , &winerror |
1873 | #endif |
1874 | )) |
1875 | goto error; |
1876 | |
1877 | if (oserror_init(self, &args, myerrno, strerror, filename, filename2 Branch (1877:9): [True: 0, False: 7]
|
1878 | #ifdef MS_WINDOWS |
1879 | , winerror |
1880 | #endif |
1881 | )) |
1882 | goto error; |
1883 | |
1884 | return 0; |
1885 | |
1886 | error: |
1887 | Py_DECREF(args); |
1888 | return -1; |
1889 | } |
1890 | |
1891 | static int |
1892 | OSError_clear(PyOSErrorObject *self) |
1893 | { |
1894 | Py_CLEAR(self->myerrno); |
1895 | Py_CLEAR(self->strerror); |
1896 | Py_CLEAR(self->filename); |
1897 | Py_CLEAR(self->filename2); |
1898 | #ifdef MS_WINDOWS |
1899 | Py_CLEAR(self->winerror); |
1900 | #endif |
1901 | return BaseException_clear((PyBaseExceptionObject *)self); |
1902 | } |
1903 | |
1904 | static void |
1905 | OSError_dealloc(PyOSErrorObject *self) |
1906 | { |
1907 | _PyObject_GC_UNTRACK(self); |
1908 | OSError_clear(self); |
1909 | Py_TYPE(self)->tp_free((PyObject *)self); |
1910 | } |
1911 | |
1912 | static int |
1913 | OSError_traverse(PyOSErrorObject *self, visitproc visit, |
1914 | void *arg) |
1915 | { |
1916 | Py_VISIT(self->myerrno); |
1917 | Py_VISIT(self->strerror); |
1918 | Py_VISIT(self->filename); |
1919 | Py_VISIT(self->filename2); |
1920 | #ifdef MS_WINDOWS |
1921 | Py_VISIT(self->winerror); |
1922 | #endif |
1923 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
1924 | } |
1925 | |
1926 | static PyObject * |
1927 | OSError_str(PyOSErrorObject *self) |
1928 | { |
1929 | #define OR_NONE(x) ((x)?(x):Py_None0 ) |
1930 | #ifdef MS_WINDOWS |
1931 | /* If available, winerror has the priority over myerrno */ |
1932 | if (self->winerror && self->filename) { |
1933 | if (self->filename2) { |
1934 | return PyUnicode_FromFormat("[WinError %S] %S: %R -> %R", |
1935 | OR_NONE(self->winerror), |
1936 | OR_NONE(self->strerror), |
1937 | self->filename, |
1938 | self->filename2); |
1939 | } else { |
1940 | return PyUnicode_FromFormat("[WinError %S] %S: %R", |
1941 | OR_NONE(self->winerror), |
1942 | OR_NONE(self->strerror), |
1943 | self->filename); |
1944 | } |
1945 | } |
1946 | if (self->winerror && self->strerror) |
1947 | return PyUnicode_FromFormat("[WinError %S] %S", |
1948 | self->winerror ? self->winerror: Py_None, |
1949 | self->strerror ? self->strerror: Py_None); |
1950 | #endif |
1951 | if (self->filename) { Branch (1951:9): [True: 114, False: 65]
|
1952 | if (self->filename2) { Branch (1952:13): [True: 4, False: 110]
|
1953 | return PyUnicode_FromFormat("[Errno %S] %S: %R -> %R", |
1954 | OR_NONE(self->myerrno), |
1955 | OR_NONE(self->strerror), |
1956 | self->filename, |
1957 | self->filename2); |
1958 | } else { |
1959 | return PyUnicode_FromFormat("[Errno %S] %S: %R", |
1960 | OR_NONE(self->myerrno), |
1961 | OR_NONE(self->strerror), |
1962 | self->filename); |
1963 | } |
1964 | } |
1965 | if (self->myerrno && self->strerror10 ) Branch (1965:9): [True: 10, False: 55]
Branch (1965:26): [True: 10, False: 0]
|
1966 | return PyUnicode_FromFormat("[Errno %S] %S", |
1967 | self->myerrno, self->strerror); |
1968 | return BaseException_str((PyBaseExceptionObject *)self); |
1969 | } |
1970 | |
1971 | static PyObject * |
1972 | OSError_reduce(PyOSErrorObject *self, PyObject *Py_UNUSED(ignored)) |
1973 | { |
1974 | PyObject *args = self->args; |
1975 | PyObject *res = NULL, *tmp; |
1976 | |
1977 | /* self->args is only the first two real arguments if there was a |
1978 | * file name given to OSError. */ |
1979 | if (PyTuple_GET_SIZE(args) == 2 && self->filename30 ) { Branch (1979:9): [True: 30, False: 6]
Branch (1979:40): [True: 24, False: 6]
|
1980 | Py_ssize_t size = self->filename2 ? 56 : 318 ; Branch (1980:27): [True: 6, False: 18]
|
1981 | args = PyTuple_New(size); |
1982 | if (!args) Branch (1982:13): [True: 0, False: 24]
|
1983 | return NULL; |
1984 | |
1985 | tmp = PyTuple_GET_ITEM(self->args, 0); |
1986 | Py_INCREF(tmp); |
1987 | PyTuple_SET_ITEM(args, 0, tmp); |
1988 | |
1989 | tmp = PyTuple_GET_ITEM(self->args, 1); |
1990 | Py_INCREF(tmp); |
1991 | PyTuple_SET_ITEM(args, 1, tmp); |
1992 | |
1993 | Py_INCREF(self->filename); |
1994 | PyTuple_SET_ITEM(args, 2, self->filename); |
1995 | |
1996 | if (self->filename2) { Branch (1996:13): [True: 6, False: 18]
|
1997 | /* |
1998 | * This tuple is essentially used as OSError(*args). |
1999 | * So, to recreate filename2, we need to pass in |
2000 | * winerror as well. |
2001 | */ |
2002 | Py_INCREF(Py_None); |
2003 | PyTuple_SET_ITEM(args, 3, Py_None); |
2004 | |
2005 | /* filename2 */ |
2006 | Py_INCREF(self->filename2); |
2007 | PyTuple_SET_ITEM(args, 4, self->filename2); |
2008 | } |
2009 | } else |
2010 | Py_INCREF(args); |
2011 | |
2012 | if (self->dict) Branch (2012:9): [True: 0, False: 36]
|
2013 | res = PyTuple_Pack(3, Py_TYPE(self), args, self->dict); |
2014 | else |
2015 | res = PyTuple_Pack(2, Py_TYPE(self), args); |
2016 | Py_DECREF(args); |
2017 | return res; |
2018 | } |
2019 | |
2020 | static PyObject * |
2021 | OSError_written_get(PyOSErrorObject *self, void *context) |
2022 | { |
2023 | if (self->written == -1) { Branch (2023:9): [True: 7, False: 30]
|
2024 | PyErr_SetString(PyExc_AttributeError, "characters_written"); |
2025 | return NULL; |
2026 | } |
2027 | return PyLong_FromSsize_t(self->written); |
2028 | } |
2029 | |
2030 | static int |
2031 | OSError_written_set(PyOSErrorObject *self, PyObject *arg, void *context) |
2032 | { |
2033 | if (arg == NULL) { Branch (2033:9): [True: 7, False: 1]
|
2034 | if (self->written == -1) { Branch (2034:13): [True: 6, False: 1]
|
2035 | PyErr_SetString(PyExc_AttributeError, "characters_written"); |
2036 | return -1; |
2037 | } |
2038 | self->written = -1; |
2039 | return 0; |
2040 | } |
2041 | Py_ssize_t n; |
2042 | n = PyNumber_AsSsize_t(arg, PyExc_ValueError); |
2043 | if (n == -1 && PyErr_Occurred()0 ) Branch (2043:9): [True: 0, False: 1]
Branch (2043:20): [True: 0, False: 0]
|
2044 | return -1; |
2045 | self->written = n; |
2046 | return 0; |
2047 | } |
2048 | |
2049 | static PyMemberDef OSError_members[] = { |
2050 | {"errno", T_OBJECT, offsetof(PyOSErrorObject, myerrno), 0, |
2051 | PyDoc_STR("POSIX exception code")}, |
2052 | {"strerror", T_OBJECT, offsetof(PyOSErrorObject, strerror), 0, |
2053 | PyDoc_STR("exception strerror")}, |
2054 | {"filename", T_OBJECT, offsetof(PyOSErrorObject, filename), 0, |
2055 | PyDoc_STR("exception filename")}, |
2056 | {"filename2", T_OBJECT, offsetof(PyOSErrorObject, filename2), 0, |
2057 | PyDoc_STR("second exception filename")}, |
2058 | #ifdef MS_WINDOWS |
2059 | {"winerror", T_OBJECT, offsetof(PyOSErrorObject, winerror), 0, |
2060 | PyDoc_STR("Win32 exception code")}, |
2061 | #endif |
2062 | {NULL} /* Sentinel */ |
2063 | }; |
2064 | |
2065 | static PyMethodDef OSError_methods[] = { |
2066 | {"__reduce__", (PyCFunction)OSError_reduce, METH_NOARGS}, |
2067 | {NULL} |
2068 | }; |
2069 | |
2070 | static PyGetSetDef OSError_getset[] = { |
2071 | {"characters_written", (getter) OSError_written_get, |
2072 | (setter) OSError_written_set, NULL}, |
2073 | {NULL} |
2074 | }; |
2075 | |
2076 | |
2077 | ComplexExtendsException(PyExc_Exception, OSError, |
2078 | OSError, OSError_new, |
2079 | OSError_methods, OSError_members, OSError_getset, |
2080 | OSError_str, |
2081 | "Base class for I/O related errors."); |
2082 | |
2083 | |
2084 | /* |
2085 | * Various OSError subclasses |
2086 | */ |
2087 | MiddlingExtendsException(PyExc_OSError, BlockingIOError, OSError, |
2088 | "I/O operation would block."); |
2089 | MiddlingExtendsException(PyExc_OSError, ConnectionError, OSError, |
2090 | "Connection error."); |
2091 | MiddlingExtendsException(PyExc_OSError, ChildProcessError, OSError, |
2092 | "Child process error."); |
2093 | MiddlingExtendsException(PyExc_ConnectionError, BrokenPipeError, OSError, |
2094 | "Broken pipe."); |
2095 | MiddlingExtendsException(PyExc_ConnectionError, ConnectionAbortedError, OSError, |
2096 | "Connection aborted."); |
2097 | MiddlingExtendsException(PyExc_ConnectionError, ConnectionRefusedError, OSError, |
2098 | "Connection refused."); |
2099 | MiddlingExtendsException(PyExc_ConnectionError, ConnectionResetError, OSError, |
2100 | "Connection reset."); |
2101 | MiddlingExtendsException(PyExc_OSError, FileExistsError, OSError, |
2102 | "File already exists."); |
2103 | MiddlingExtendsException(PyExc_OSError, FileNotFoundError, OSError, |
2104 | "File not found."); |
2105 | MiddlingExtendsException(PyExc_OSError, IsADirectoryError, OSError, |
2106 | "Operation doesn't work on directories."); |
2107 | MiddlingExtendsException(PyExc_OSError, NotADirectoryError, OSError, |
2108 | "Operation only works on directories."); |
2109 | MiddlingExtendsException(PyExc_OSError, InterruptedError, OSError, |
2110 | "Interrupted by signal."); |
2111 | MiddlingExtendsException(PyExc_OSError, PermissionError, OSError, |
2112 | "Not enough permissions."); |
2113 | MiddlingExtendsException(PyExc_OSError, ProcessLookupError, OSError, |
2114 | "Process not found."); |
2115 | MiddlingExtendsException(PyExc_OSError, TimeoutError, OSError, |
2116 | "Timeout expired."); |
2117 | |
2118 | /* |
2119 | * EOFError extends Exception |
2120 | */ |
2121 | SimpleExtendsException(PyExc_Exception, EOFError, |
2122 | "Read beyond end of file."); |
2123 | |
2124 | |
2125 | /* |
2126 | * RuntimeError extends Exception |
2127 | */ |
2128 | SimpleExtendsException(PyExc_Exception, RuntimeError, |
2129 | "Unspecified run-time error."); |
2130 | |
2131 | /* |
2132 | * RecursionError extends RuntimeError |
2133 | */ |
2134 | SimpleExtendsException(PyExc_RuntimeError, RecursionError, |
2135 | "Recursion limit exceeded."); |
2136 | |
2137 | /* |
2138 | * NotImplementedError extends RuntimeError |
2139 | */ |
2140 | SimpleExtendsException(PyExc_RuntimeError, NotImplementedError, |
2141 | "Method or function hasn't been implemented yet."); |
2142 | |
2143 | /* |
2144 | * NameError extends Exception |
2145 | */ |
2146 | |
2147 | static int |
2148 | NameError_init(PyNameErrorObject *self, PyObject *args, PyObject *kwds) |
2149 | { |
2150 | static char *kwlist[] = {"name", NULL}; |
2151 | PyObject *name = NULL; |
2152 | |
2153 | if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) { Branch (2153:9): [True: 0, False: 210]
|
2154 | return -1; |
2155 | } |
2156 | |
2157 | PyObject *empty_tuple = PyTuple_New(0); |
2158 | if (!empty_tuple) { Branch (2158:9): [True: 0, False: 210]
|
2159 | return -1; |
2160 | } |
2161 | if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$O:NameError", kwlist, Branch (2161:9): [True: 0, False: 210]
|
2162 | &name)) { |
2163 | Py_DECREF(empty_tuple); |
2164 | return -1; |
2165 | } |
2166 | Py_DECREF(empty_tuple); |
2167 | |
2168 | Py_XINCREF(name); |
2169 | Py_XSETREF(self->name, name); |
2170 | |
2171 | return 0; |
2172 | } |
2173 | |
2174 | static int |
2175 | NameError_clear(PyNameErrorObject *self) |
2176 | { |
2177 | Py_CLEAR(self->name); |
2178 | return BaseException_clear((PyBaseExceptionObject *)self); |
2179 | } |
2180 | |
2181 | static void |
2182 | NameError_dealloc(PyNameErrorObject *self) |
2183 | { |
2184 | _PyObject_GC_UNTRACK(self); |
2185 | NameError_clear(self); |
2186 | Py_TYPE(self)->tp_free((PyObject *)self); |
2187 | } |
2188 | |
2189 | static int |
2190 | NameError_traverse(PyNameErrorObject *self, visitproc visit, void *arg) |
2191 | { |
2192 | Py_VISIT(self->name); |
2193 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
2194 | } |
2195 | |
2196 | static PyMemberDef NameError_members[] = { |
2197 | {"name", T_OBJECT, offsetof(PyNameErrorObject, name), 0, PyDoc_STR("name")}, |
2198 | {NULL} /* Sentinel */ |
2199 | }; |
2200 | |
2201 | static PyMethodDef NameError_methods[] = { |
2202 | {NULL} /* Sentinel */ |
2203 | }; |
2204 | |
2205 | ComplexExtendsException(PyExc_Exception, NameError, |
2206 | NameError, 0, |
2207 | NameError_methods, NameError_members, |
2208 | 0, BaseException_str, "Name not found globally."); |
2209 | |
2210 | /* |
2211 | * UnboundLocalError extends NameError |
2212 | */ |
2213 | |
2214 | MiddlingExtendsException(PyExc_NameError, UnboundLocalError, NameError, |
2215 | "Local name referenced but not bound to a value."); |
2216 | |
2217 | /* |
2218 | * AttributeError extends Exception |
2219 | */ |
2220 | |
2221 | static int |
2222 | AttributeError_init(PyAttributeErrorObject *self, PyObject *args, PyObject *kwds) |
2223 | { |
2224 | static char *kwlist[] = {"name", "obj", NULL}; |
2225 | PyObject *name = NULL; |
2226 | PyObject *obj = NULL; |
2227 | |
2228 | if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) { Branch (2228:9): [True: 0, False: 494k]
|
2229 | return -1; |
2230 | } |
2231 | |
2232 | PyObject *empty_tuple = PyTuple_New(0); |
2233 | if (!empty_tuple) { Branch (2233:9): [True: 0, False: 494k]
|
2234 | return -1; |
2235 | } |
2236 | if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OO:AttributeError", kwlist, Branch (2236:9): [True: 0, False: 494k]
|
2237 | &name, &obj)) { |
2238 | Py_DECREF(empty_tuple); |
2239 | return -1; |
2240 | } |
2241 | Py_DECREF(empty_tuple); |
2242 | |
2243 | Py_XINCREF(name); |
2244 | Py_XSETREF(self->name, name); |
2245 | |
2246 | Py_XINCREF(obj); |
2247 | Py_XSETREF(self->obj, obj); |
2248 | |
2249 | return 0; |
2250 | } |
2251 | |
2252 | static int |
2253 | AttributeError_clear(PyAttributeErrorObject *self) |
2254 | { |
2255 | Py_CLEAR(self->obj); |
2256 | Py_CLEAR(self->name); |
2257 | return BaseException_clear((PyBaseExceptionObject *)self); |
2258 | } |
2259 | |
2260 | static void |
2261 | AttributeError_dealloc(PyAttributeErrorObject *self) |
2262 | { |
2263 | _PyObject_GC_UNTRACK(self); |
2264 | AttributeError_clear(self); |
2265 | Py_TYPE(self)->tp_free((PyObject *)self); |
2266 | } |
2267 | |
2268 | static int |
2269 | AttributeError_traverse(PyAttributeErrorObject *self, visitproc visit, void *arg) |
2270 | { |
2271 | Py_VISIT(self->obj); |
2272 | Py_VISIT(self->name); |
2273 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
2274 | } |
2275 | |
2276 | static PyMemberDef AttributeError_members[] = { |
2277 | {"name", T_OBJECT, offsetof(PyAttributeErrorObject, name), 0, PyDoc_STR("attribute name")}, |
2278 | {"obj", T_OBJECT, offsetof(PyAttributeErrorObject, obj), 0, PyDoc_STR("object")}, |
2279 | {NULL} /* Sentinel */ |
2280 | }; |
2281 | |
2282 | static PyMethodDef AttributeError_methods[] = { |
2283 | {NULL} /* Sentinel */ |
2284 | }; |
2285 | |
2286 | ComplexExtendsException(PyExc_Exception, AttributeError, |
2287 | AttributeError, 0, |
2288 | AttributeError_methods, AttributeError_members, |
2289 | 0, BaseException_str, "Attribute not found."); |
2290 | |
2291 | /* |
2292 | * SyntaxError extends Exception |
2293 | */ |
2294 | |
2295 | static int |
2296 | SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds) |
2297 | { |
2298 | PyObject *info = NULL; |
2299 | Py_ssize_t lenargs = PyTuple_GET_SIZE(args); |
2300 | |
2301 | if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) Branch (2301:9): [True: 0, False: 2.48k]
|
2302 | return -1; |
2303 | |
2304 | if (lenargs >= 1) { Branch (2304:9): [True: 2.44k, False: 39]
|
2305 | Py_INCREF(PyTuple_GET_ITEM(args, 0)); |
2306 | Py_XSETREF(self->msg, PyTuple_GET_ITEM(args, 0)); |
2307 | } |
2308 | if (lenargs == 2) { Branch (2308:9): [True: 2.14k, False: 339]
|
2309 | info = PyTuple_GET_ITEM(args, 1); |
2310 | info = PySequence_Tuple(info); |
2311 | if (!info) { Branch (2311:13): [True: 0, False: 2.14k]
|
2312 | return -1; |
2313 | } |
2314 | |
2315 | self->end_lineno = NULL; |
2316 | self->end_offset = NULL; |
2317 | if (!PyArg_ParseTuple(info, "OOOO|OO", Branch (2317:13): [True: 2, False: 2.14k]
|
2318 | &self->filename, &self->lineno, |
2319 | &self->offset, &self->text, |
2320 | &self->end_lineno, &self->end_offset)) { |
2321 | Py_DECREF(info); |
2322 | return -1; |
2323 | } |
2324 | |
2325 | Py_INCREF(self->filename); |
2326 | Py_INCREF(self->lineno); |
2327 | Py_INCREF(self->offset); |
2328 | Py_INCREF(self->text); |
2329 | Py_XINCREF(self->end_lineno); |
2330 | Py_XINCREF(self->end_offset); |
2331 | Py_DECREF(info); |
2332 | |
2333 | if (self->end_lineno != NULL && self->end_offset == NULL2.04k ) { Branch (2333:13): [True: 2.04k, False: 105]
Branch (2333:41): [True: 1, False: 2.03k]
|
2334 | PyErr_SetString(PyExc_TypeError, "end_offset must be provided when end_lineno is provided"); |
2335 | return -1; |
2336 | } |
2337 | } |
2338 | return 0; |
2339 | } |
2340 | |
2341 | static int |
2342 | SyntaxError_clear(PySyntaxErrorObject *self) |
2343 | { |
2344 | Py_CLEAR(self->msg); |
2345 | Py_CLEAR(self->filename); |
2346 | Py_CLEAR(self->lineno); |
2347 | Py_CLEAR(self->offset); |
2348 | Py_CLEAR(self->end_lineno); |
2349 | Py_CLEAR(self->end_offset); |
2350 | Py_CLEAR(self->text); |
2351 | Py_CLEAR(self->print_file_and_line); |
2352 | return BaseException_clear((PyBaseExceptionObject *)self); |
2353 | } |
2354 | |
2355 | static void |
2356 | SyntaxError_dealloc(PySyntaxErrorObject *self) |
2357 | { |
2358 | _PyObject_GC_UNTRACK(self); |
2359 | SyntaxError_clear(self); |
2360 | Py_TYPE(self)->tp_free((PyObject *)self); |
2361 | } |
2362 | |
2363 | static int |
2364 | SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg) |
2365 | { |
2366 | Py_VISIT(self->msg); |
2367 | Py_VISIT(self->filename); |
2368 | Py_VISIT(self->lineno); |
2369 | Py_VISIT(self->offset); |
2370 | Py_VISIT(self->end_lineno); |
2371 | Py_VISIT(self->end_offset); |
2372 | Py_VISIT(self->text); |
2373 | Py_VISIT(self->print_file_and_line); |
2374 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
2375 | } |
2376 | |
2377 | /* This is called "my_basename" instead of just "basename" to avoid name |
2378 | conflicts with glibc; basename is already prototyped if _GNU_SOURCE is |
2379 | defined, and Python does define that. */ |
2380 | static PyObject* |
2381 | my_basename(PyObject *name) |
2382 | { |
2383 | Py_ssize_t i, size, offset; |
2384 | int kind; |
2385 | const void *data; |
2386 | |
2387 | if (PyUnicode_READY(name)) |
2388 | return NULL; |
2389 | kind = PyUnicode_KIND(name); |
2390 | data = PyUnicode_DATA(name); |
2391 | size = PyUnicode_GET_LENGTH(name); |
2392 | offset = 0; |
2393 | for(i=0; i < size; i++33.3k ) { Branch (2393:14): [True: 33.3k, False: 1.72k]
|
2394 | if (PyUnicode_READ(kind, data, i) == SEP) { Branch (2394:13): [True: 272, False: 33.0k]
|
2395 | offset = i + 1; |
2396 | } |
2397 | } |
2398 | if (offset != 0) { Branch (2398:9): [True: 41, False: 1.67k]
|
2399 | return PyUnicode_Substring(name, offset, size); |
2400 | } |
2401 | else { |
2402 | Py_INCREF(name); |
2403 | return name; |
2404 | } |
2405 | } |
2406 | |
2407 | |
2408 | static PyObject * |
2409 | SyntaxError_str(PySyntaxErrorObject *self) |
2410 | { |
2411 | int have_lineno = 0; |
2412 | PyObject *filename; |
2413 | PyObject *result; |
2414 | /* Below, we always ignore overflow errors, just printing -1. |
2415 | Still, we cannot allow an OverflowError to be raised, so |
2416 | we need to call PyLong_AsLongAndOverflow. */ |
2417 | int overflow; |
2418 | |
2419 | /* XXX -- do all the additional formatting with filename and |
2420 | lineno here */ |
2421 | |
2422 | if (self->filename && PyUnicode_Check1.72k (self->filename)) { Branch (2422:9): [True: 1.72k, False: 57]
|
2423 | filename = my_basename(self->filename); |
2424 | if (filename == NULL) Branch (2424:13): [True: 0, False: 1.72k]
|
2425 | return NULL; |
2426 | } else { |
2427 | filename = NULL; |
2428 | } |
2429 | have_lineno = (self->lineno != NULL) && PyLong_CheckExact(self->lineno); Branch (2429:19): [True: 1.71k, False: 58]
|
2430 | |
2431 | if (!filename && !have_lineno57 ) Branch (2431:9): [True: 57, False: 1.72k]
Branch (2431:22): [True: 55, False: 2]
|
2432 | return PyObject_Str(self->msg ? self->msg54 : Py_None1 ); Branch (2432:29): [True: 54, False: 1]
|
2433 | |
2434 | if (filename && have_lineno1.72k ) Branch (2434:9): [True: 1.72k, False: 2]
Branch (2434:21): [True: 1.71k, False: 4]
|
2435 | result = PyUnicode_FromFormat("%S (%U, line %ld)", |
2436 | self->msg ? self->msg : Py_None0 , Branch (2436:20): [True: 1.71k, False: 0]
|
2437 | filename, |
2438 | PyLong_AsLongAndOverflow(self->lineno, &overflow)); |
2439 | else if (filename) Branch (2439:14): [True: 4, False: 2]
|
2440 | result = PyUnicode_FromFormat("%S (%U)", |
2441 | self->msg ? self->msg : Py_None0 , Branch (2441:20): [True: 4, False: 0]
|
2442 | filename); |
2443 | else /* only have_lineno */ |
2444 | result = PyUnicode_FromFormat("%S (line %ld)", |
2445 | self->msg ? self->msg : Py_None0 , Branch (2445:20): [True: 2, False: 0]
|
2446 | PyLong_AsLongAndOverflow(self->lineno, &overflow)); |
2447 | Py_XDECREF(filename); |
2448 | return result; |
2449 | } |
2450 | |
2451 | static PyMemberDef SyntaxError_members[] = { |
2452 | {"msg", T_OBJECT, offsetof(PySyntaxErrorObject, msg), 0, |
2453 | PyDoc_STR("exception msg")}, |
2454 | {"filename", T_OBJECT, offsetof(PySyntaxErrorObject, filename), 0, |
2455 | PyDoc_STR("exception filename")}, |
2456 | {"lineno", T_OBJECT, offsetof(PySyntaxErrorObject, lineno), 0, |
2457 | PyDoc_STR("exception lineno")}, |
2458 | {"offset", T_OBJECT, offsetof(PySyntaxErrorObject, offset), 0, |
2459 | PyDoc_STR("exception offset")}, |
2460 | {"text", T_OBJECT, offsetof(PySyntaxErrorObject, text), 0, |
2461 | PyDoc_STR("exception text")}, |
2462 | {"end_lineno", T_OBJECT, offsetof(PySyntaxErrorObject, end_lineno), 0, |
2463 | PyDoc_STR("exception end lineno")}, |
2464 | {"end_offset", T_OBJECT, offsetof(PySyntaxErrorObject, end_offset), 0, |
2465 | PyDoc_STR("exception end offset")}, |
2466 | {"print_file_and_line", T_OBJECT, |
2467 | offsetof(PySyntaxErrorObject, print_file_and_line), 0, |
2468 | PyDoc_STR("exception print_file_and_line")}, |
2469 | {NULL} /* Sentinel */ |
2470 | }; |
2471 | |
2472 | ComplexExtendsException(PyExc_Exception, SyntaxError, SyntaxError, |
2473 | 0, 0, SyntaxError_members, 0, |
2474 | SyntaxError_str, "Invalid syntax."); |
2475 | |
2476 | |
2477 | /* |
2478 | * IndentationError extends SyntaxError |
2479 | */ |
2480 | MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError, |
2481 | "Improper indentation."); |
2482 | |
2483 | |
2484 | /* |
2485 | * TabError extends IndentationError |
2486 | */ |
2487 | MiddlingExtendsException(PyExc_IndentationError, TabError, SyntaxError, |
2488 | "Improper mixture of spaces and tabs."); |
2489 | |
2490 | |
2491 | /* |
2492 | * LookupError extends Exception |
2493 | */ |
2494 | SimpleExtendsException(PyExc_Exception, LookupError, |
2495 | "Base class for lookup errors."); |
2496 | |
2497 | |
2498 | /* |
2499 | * IndexError extends LookupError |
2500 | */ |
2501 | SimpleExtendsException(PyExc_LookupError, IndexError, |
2502 | "Sequence index out of range."); |
2503 | |
2504 | |
2505 | /* |
2506 | * KeyError extends LookupError |
2507 | */ |
2508 | static PyObject * |
2509 | KeyError_str(PyBaseExceptionObject *self) |
2510 | { |
2511 | /* If args is a tuple of exactly one item, apply repr to args[0]. |
2512 | This is done so that e.g. the exception raised by {}[''] prints |
2513 | KeyError: '' |
2514 | rather than the confusing |
2515 | KeyError |
2516 | alone. The downside is that if KeyError is raised with an explanatory |
2517 | string, that string will be displayed in quotes. Too bad. |
2518 | If args is anything else, use the default BaseException__str__(). |
2519 | */ |
2520 | if (PyTuple_GET_SIZE(self->args) == 1) { Branch (2520:9): [True: 19, False: 22]
|
2521 | return PyObject_Repr(PyTuple_GET_ITEM(self->args, 0)); |
2522 | } |
2523 | return BaseException_str(self); |
2524 | } |
2525 | |
2526 | ComplexExtendsException(PyExc_LookupError, KeyError, BaseException, |
2527 | 0, 0, 0, 0, KeyError_str, "Mapping key not found."); |
2528 | |
2529 | |
2530 | /* |
2531 | * ValueError extends Exception |
2532 | */ |
2533 | SimpleExtendsException(PyExc_Exception, ValueError, |
2534 | "Inappropriate argument value (of correct type)."); |
2535 | |
2536 | /* |
2537 | * UnicodeError extends ValueError |
2538 | */ |
2539 | |
2540 | SimpleExtendsException(PyExc_ValueError, UnicodeError, |
2541 | "Unicode related error."); |
2542 | |
2543 | static PyObject * |
2544 | get_string(PyObject *attr, const char *name) |
2545 | { |
2546 | if (!attr) { Branch (2546:9): [True: 0, False: 5.98k]
|
2547 | PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name); |
2548 | return NULL; |
2549 | } |
2550 | |
2551 | if (!PyBytes_Check(attr)) { Branch (2551:9): [True: 8, False: 5.97k]
|
2552 | PyErr_Format(PyExc_TypeError, "%.200s attribute must be bytes", name); |
2553 | return NULL; |
2554 | } |
2555 | Py_INCREF(attr); |
2556 | return attr; |
2557 | } |
2558 | |
2559 | static PyObject * |
2560 | get_unicode(PyObject *attr, const char *name) |
2561 | { |
2562 | if (!attr) { Branch (2562:9): [True: 0, False: 18.9k]
|
2563 | PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name); |
2564 | return NULL; |
2565 | } |
2566 | |
2567 | if (!PyUnicode_Check(attr)) { Branch (2567:9): [True: 1, False: 18.9k]
|
2568 | PyErr_Format(PyExc_TypeError, |
2569 | "%.200s attribute must be unicode", name); |
2570 | return NULL; |
2571 | } |
2572 | Py_INCREF(attr); |
2573 | return attr; |
2574 | } |
2575 | |
2576 | static int |
2577 | set_unicodefromstring(PyObject **attr, const char *value) |
2578 | { |
2579 | PyObject *obj = PyUnicode_FromString(value); |
2580 | if (!obj) Branch (2580:9): [True: 0, False: 10.7k]
|
2581 | return -1; |
2582 | Py_XSETREF(*attr, obj); |
2583 | return 0; |
2584 | } |
2585 | |
2586 | PyObject * |
2587 | PyUnicodeEncodeError_GetEncoding(PyObject *exc) |
2588 | { |
2589 | return get_unicode(((PyUnicodeErrorObject *)exc)->encoding, "encoding"); |
2590 | } |
2591 | |
2592 | PyObject * |
2593 | PyUnicodeDecodeError_GetEncoding(PyObject *exc) |
2594 | { |
2595 | return get_unicode(((PyUnicodeErrorObject *)exc)->encoding, "encoding"); |
2596 | } |
2597 | |
2598 | PyObject * |
2599 | PyUnicodeEncodeError_GetObject(PyObject *exc) |
2600 | { |
2601 | return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object"); |
2602 | } |
2603 | |
2604 | PyObject * |
2605 | PyUnicodeDecodeError_GetObject(PyObject *exc) |
2606 | { |
2607 | return get_string(((PyUnicodeErrorObject *)exc)->object, "object"); |
2608 | } |
2609 | |
2610 | PyObject * |
2611 | PyUnicodeTranslateError_GetObject(PyObject *exc) |
2612 | { |
2613 | return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object"); |
2614 | } |
2615 | |
2616 | int |
2617 | PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start) |
2618 | { |
2619 | Py_ssize_t size; |
2620 | PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object, |
2621 | "object"); |
2622 | if (!obj) Branch (2622:9): [True: 1, False: 5.29k]
|
2623 | return -1; |
2624 | *start = ((PyUnicodeErrorObject *)exc)->start; |
2625 | size = PyUnicode_GET_LENGTH(obj); |
2626 | if (*start<0) Branch (2626:9): [True: 0, False: 5.29k]
|
2627 | *start = 0; /*XXX check for values <0*/ |
2628 | if (*start>=size) Branch (2628:9): [True: 0, False: 5.29k]
|
2629 | *start = size-1; |
2630 | Py_DECREF(obj); |
2631 | return 0; |
2632 | } |
2633 | |
2634 | |
2635 | int |
2636 | PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start) |
2637 | { |
2638 | Py_ssize_t size; |
2639 | PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object, "object"); |
2640 | if (!obj) Branch (2640:9): [True: 0, False: 671]
|
2641 | return -1; |
2642 | size = PyBytes_GET_SIZE(obj); |
2643 | *start = ((PyUnicodeErrorObject *)exc)->start; |
2644 | if (*start<0) Branch (2644:9): [True: 0, False: 671]
|
2645 | *start = 0; |
2646 | if (*start>=size) Branch (2646:9): [True: 0, False: 671]
|
2647 | *start = size-1; |
2648 | Py_DECREF(obj); |
2649 | return 0; |
2650 | } |
2651 | |
2652 | |
2653 | int |
2654 | PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start) |
2655 | { |
2656 | return PyUnicodeEncodeError_GetStart(exc, start); |
2657 | } |
2658 | |
2659 | |
2660 | int |
2661 | PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start) |
2662 | { |
2663 | ((PyUnicodeErrorObject *)exc)->start = start; |
2664 | return 0; |
2665 | } |
2666 | |
2667 | |
2668 | int |
2669 | PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start) |
2670 | { |
2671 | ((PyUnicodeErrorObject *)exc)->start = start; |
2672 | return 0; |
2673 | } |
2674 | |
2675 | |
2676 | int |
2677 | PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start) |
2678 | { |
2679 | ((PyUnicodeErrorObject *)exc)->start = start; |
2680 | return 0; |
2681 | } |
2682 | |
2683 | |
2684 | int |
2685 | PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end) |
2686 | { |
2687 | Py_ssize_t size; |
2688 | PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object, |
2689 | "object"); |
2690 | if (!obj) Branch (2690:9): [True: 0, False: 8.71k]
|
2691 | return -1; |
2692 | *end = ((PyUnicodeErrorObject *)exc)->end; |
2693 | size = PyUnicode_GET_LENGTH(obj); |
2694 | if (*end<1) Branch (2694:9): [True: 0, False: 8.71k]
|
2695 | *end = 1; |
2696 | if (*end>size) Branch (2696:9): [True: 0, False: 8.71k]
|
2697 | *end = size; |
2698 | Py_DECREF(obj); |
2699 | return 0; |
2700 | } |
2701 | |
2702 | |
2703 | int |
2704 | PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end) |
2705 | { |
2706 | Py_ssize_t size; |
2707 | PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object, "object"); |
2708 | if (!obj) Branch (2708:9): [True: 1, False: 2.18k]
|
2709 | return -1; |
2710 | size = PyBytes_GET_SIZE(obj); |
2711 | *end = ((PyUnicodeErrorObject *)exc)->end; |
2712 | if (*end<1) Branch (2712:9): [True: 0, False: 2.18k]
|
2713 | *end = 1; |
2714 | if (*end>size) Branch (2714:9): [True: 0, False: 2.18k]
|
2715 | *end = size; |
2716 | Py_DECREF(obj); |
2717 | return 0; |
2718 | } |
2719 | |
2720 | |
2721 | int |
2722 | PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *end) |
2723 | { |
2724 | return PyUnicodeEncodeError_GetEnd(exc, end); |
2725 | } |
2726 | |
2727 | |
2728 | int |
2729 | PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end) |
2730 | { |
2731 | ((PyUnicodeErrorObject *)exc)->end = end; |
2732 | return 0; |
2733 | } |
2734 | |
2735 | |
2736 | int |
2737 | PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end) |
2738 | { |
2739 | ((PyUnicodeErrorObject *)exc)->end = end; |
2740 | return 0; |
2741 | } |
2742 | |
2743 | |
2744 | int |
2745 | PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end) |
2746 | { |
2747 | ((PyUnicodeErrorObject *)exc)->end = end; |
2748 | return 0; |
2749 | } |
2750 | |
2751 | PyObject * |
2752 | PyUnicodeEncodeError_GetReason(PyObject *exc) |
2753 | { |
2754 | return get_unicode(((PyUnicodeErrorObject *)exc)->reason, "reason"); |
2755 | } |
2756 | |
2757 | |
2758 | PyObject * |
2759 | PyUnicodeDecodeError_GetReason(PyObject *exc) |
2760 | { |
2761 | return get_unicode(((PyUnicodeErrorObject *)exc)->reason, "reason"); |
2762 | } |
2763 | |
2764 | |
2765 | PyObject * |
2766 | PyUnicodeTranslateError_GetReason(PyObject *exc) |
2767 | { |
2768 | return get_unicode(((PyUnicodeErrorObject *)exc)->reason, "reason"); |
2769 | } |
2770 | |
2771 | |
2772 | int |
2773 | PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason) |
2774 | { |
2775 | return set_unicodefromstring(&((PyUnicodeErrorObject *)exc)->reason, |
2776 | reason); |
2777 | } |
2778 | |
2779 | |
2780 | int |
2781 | PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason) |
2782 | { |
2783 | return set_unicodefromstring(&((PyUnicodeErrorObject *)exc)->reason, |
2784 | reason); |
2785 | } |
2786 | |
2787 | |
2788 | int |
2789 | PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason) |
2790 | { |
2791 | return set_unicodefromstring(&((PyUnicodeErrorObject *)exc)->reason, |
2792 | reason); |
2793 | } |
2794 | |
2795 | |
2796 | static int |
2797 | UnicodeError_clear(PyUnicodeErrorObject *self) |
2798 | { |
2799 | Py_CLEAR(self->encoding); |
2800 | Py_CLEAR(self->object); |
2801 | Py_CLEAR(self->reason); |
2802 | return BaseException_clear((PyBaseExceptionObject *)self); |
2803 | } |
2804 | |
2805 | static void |
2806 | UnicodeError_dealloc(PyUnicodeErrorObject *self) |
2807 | { |
2808 | _PyObject_GC_UNTRACK(self); |
2809 | UnicodeError_clear(self); |
2810 | Py_TYPE(self)->tp_free((PyObject *)self); |
2811 | } |
2812 | |
2813 | static int |
2814 | UnicodeError_traverse(PyUnicodeErrorObject *self, visitproc visit, void *arg) |
2815 | { |
2816 | Py_VISIT(self->encoding); |
2817 | Py_VISIT(self->object); |
2818 | Py_VISIT(self->reason); |
2819 | return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); |
2820 | } |
2821 | |
2822 | static PyMemberDef UnicodeError_members[] = { |
2823 | {"encoding", T_OBJECT, offsetof(PyUnicodeErrorObject, encoding), 0, |
2824 | PyDoc_STR("exception encoding")}, |
2825 | {"object", T_OBJECT, offsetof(PyUnicodeErrorObject, object), 0, |
2826 | PyDoc_STR("exception object")}, |
2827 | {"start", T_PYSSIZET, offsetof(PyUnicodeErrorObject, start), 0, |
2828 | PyDoc_STR("exception start")}, |
2829 | {"end", T_PYSSIZET, offsetof(PyUnicodeErrorObject, end), 0, |
2830 | PyDoc_STR("exception end")}, |
2831 | {"reason", T_OBJECT, offsetof(PyUnicodeErrorObject, reason), 0, |
2832 | PyDoc_STR("exception reason")}, |
2833 | {NULL} /* Sentinel */ |
2834 | }; |
2835 | |
2836 | |
2837 | /* |
2838 | * UnicodeEncodeError extends UnicodeError |
2839 | */ |
2840 | |
2841 | static int |
2842 | UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds) |
2843 | { |
2844 | PyUnicodeErrorObject *err; |
2845 | |
2846 | if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) Branch (2846:9): [True: 0, False: 2.30k]
|
2847 | return -1; |
2848 | |
2849 | err = (PyUnicodeErrorObject *)self; |
2850 | |
2851 | Py_CLEAR(err->encoding); |
2852 | Py_CLEAR(err->object); |
2853 | Py_CLEAR(err->reason); |
2854 | |
2855 | if (!PyArg_ParseTuple(args, "UUnnU", Branch (2855:9): [True: 163, False: 2.14k]
|
2856 | &err->encoding, &err->object, |
2857 | &err->start, &err->end, &err->reason)) { |
2858 | err->encoding = err->object = err->reason = NULL; |
2859 | return -1; |
2860 | } |
2861 | |
2862 | Py_INCREF(err->encoding); |
2863 | Py_INCREF(err->object); |
2864 | Py_INCREF(err->reason); |
2865 | |
2866 | return 0; |
2867 | } |
2868 | |
2869 | static PyObject * |
2870 | UnicodeEncodeError_str(PyObject *self) |
2871 | { |
2872 | PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self; |
2873 | PyObject *result = NULL; |
2874 | PyObject *reason_str = NULL; |
2875 | PyObject *encoding_str = NULL; |
2876 | |
2877 | if (!uself->object) Branch (2877:9): [True: 1, False: 17]
|
2878 | /* Not properly initialized. */ |
2879 | return PyUnicode_FromString(""); |
2880 | |
2881 | /* Get reason and encoding as strings, which they might not be if |
2882 | they've been modified after we were constructed. */ |
2883 | reason_str = PyObject_Str(uself->reason); |
2884 | if (reason_str == NULL) Branch (2884:9): [True: 0, False: 17]
|
2885 | goto done; |
2886 | encoding_str = PyObject_Str(uself->encoding); |
2887 | if (encoding_str == NULL) Branch (2887:9): [True: 0, False: 17]
|
2888 | goto done; |
2889 | |
2890 | if (uself->start < PyUnicode_GET_LENGTH(uself->object) && uself->end == uself->start+116 ) { Branch (2890:9): [True: 16, False: 1]
Branch (2890:63): [True: 11, False: 5]
|
2891 | Py_UCS4 badchar = PyUnicode_ReadChar(uself->object, uself->start); |
2892 | const char *fmt; |
2893 | if (badchar <= 0xff) Branch (2893:13): [True: 5, False: 6]
|
2894 | fmt = "'%U' codec can't encode character '\\x%02x' in position %zd: %U"; |
2895 | else if (badchar <= 0xffff) Branch (2895:18): [True: 5, False: 1]
|
2896 | fmt = "'%U' codec can't encode character '\\u%04x' in position %zd: %U"; |
2897 | else |
2898 | fmt = "'%U' codec can't encode character '\\U%08x' in position %zd: %U"; |
2899 | result = PyUnicode_FromFormat( |
2900 | fmt, |
2901 | encoding_str, |
2902 | (int)badchar, |
2903 | uself->start, |
2904 | reason_str); |
2905 | } |
2906 | else { |
2907 | result = PyUnicode_FromFormat( |
2908 | "'%U' codec can't encode characters in position %zd-%zd: %U", |
2909 | encoding_str, |
2910 | uself->start, |
2911 | uself->end-1, |
2912 | reason_str); |
2913 | } |
2914 | done: |
2915 | Py_XDECREF(reason_str); |
2916 | Py_XDECREF(encoding_str); |
2917 | return result; |
2918 | } |
2919 | |
2920 | static PyTypeObject _PyExc_UnicodeEncodeError = { |
2921 | PyVarObject_HEAD_INIT(NULL, 0) |
2922 | "UnicodeEncodeError", |
2923 | sizeof(PyUnicodeErrorObject), 0, |
2924 | (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
2925 | (reprfunc)UnicodeEncodeError_str, 0, 0, 0, |
2926 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, |
2927 | PyDoc_STR("Unicode encoding error."), (traverseproc)UnicodeError_traverse, |
2928 | (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, |
2929 | 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), |
2930 | (initproc)UnicodeEncodeError_init, 0, BaseException_new, |
2931 | }; |
2932 | PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError; |
2933 | |
2934 | |
2935 | /* |
2936 | * UnicodeDecodeError extends UnicodeError |
2937 | */ |
2938 | |
2939 | static int |
2940 | UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds) |
2941 | { |
2942 | PyUnicodeErrorObject *ude; |
2943 | |
2944 | if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) Branch (2944:9): [True: 0, False: 2.28k]
|
2945 | return -1; |
2946 | |
2947 | ude = (PyUnicodeErrorObject *)self; |
2948 | |
2949 | Py_CLEAR(ude->encoding); |
2950 | Py_CLEAR(ude->object); |
2951 | Py_CLEAR(ude->reason); |
2952 | |
2953 | if (!PyArg_ParseTuple(args, "UOnnU", Branch (2953:9): [True: 57, False: 2.22k]
|
2954 | &ude->encoding, &ude->object, |
2955 | &ude->start, &ude->end, &ude->reason)) { |
2956 | ude->encoding = ude->object = ude->reason = NULL; |
2957 | return -1; |
2958 | } |
2959 | |
2960 | Py_INCREF(ude->encoding); |
2961 | Py_INCREF(ude->object); |
2962 | Py_INCREF(ude->reason); |
2963 | |
2964 | if (!PyBytes_Check(ude->object)) { Branch (2964:9): [True: 36, False: 2.19k]
|
2965 | Py_buffer view; |
2966 | if (PyObject_GetBuffer(ude->object, &view, PyBUF_SIMPLE) != 0) Branch (2966:13): [True: 0, False: 36]
|
2967 | goto error; |
2968 | Py_XSETREF(ude->object, PyBytes_FromStringAndSize(view.buf, view.len)); |
2969 | PyBuffer_Release(&view); |
2970 | if (!ude->object) Branch (2970:13): [True: 0, False: 36]
|
2971 | goto error; |
2972 | } |
2973 | return 0; |
2974 | |
2975 | error: |
2976 | Py_CLEAR(ude->encoding); |
2977 | Py_CLEAR(ude->object); |
2978 | Py_CLEAR(ude->reason); |
2979 | return -1; |
2980 | } |
2981 | |
2982 | static PyObject * |
2983 | UnicodeDecodeError_str(PyObject *self) |
2984 | { |
2985 | PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self; |
2986 | PyObject *result = NULL; |
2987 | PyObject *reason_str = NULL; |
2988 | PyObject *encoding_str = NULL; |
2989 | |
2990 | if (!uself->object) Branch (2990:9): [True: 1, False: 297]
|
2991 | /* Not properly initialized. */ |
2992 | return PyUnicode_FromString(""); |
2993 | |
2994 | /* Get reason and encoding as strings, which they might not be if |
2995 | they've been modified after we were constructed. */ |
2996 | reason_str = PyObject_Str(uself->reason); |
2997 | if (reason_str == NULL) Branch (2997:9): [True: 0, False: 297]
|
2998 | goto done; |
2999 | encoding_str = PyObject_Str(uself->encoding); |
3000 | if (encoding_str == NULL) Branch (3000:9): [True: 0, False: 297]
|
3001 | goto done; |
3002 | |
3003 | if (uself->start < PyBytes_GET_SIZE(uself->object) && uself->end == uself->start+1296 ) { Branch (3003:9): [True: 296, False: 1]
Branch (3003:59): [True: 76, False: 220]
|
3004 | int byte = (int)(PyBytes_AS_STRING(((PyUnicodeErrorObject *)self)->object)[uself->start]&0xff); |
3005 | result = PyUnicode_FromFormat( |
3006 | "'%U' codec can't decode byte 0x%02x in position %zd: %U", |
3007 | encoding_str, |
3008 | byte, |
3009 | uself->start, |
3010 | reason_str); |
3011 | } |
3012 | else { |
3013 | result = PyUnicode_FromFormat( |
3014 | "'%U' codec can't decode bytes in position %zd-%zd: %U", |
3015 | encoding_str, |
3016 | uself->start, |
3017 | uself->end-1, |
3018 | reason_str |
3019 | ); |
3020 | } |
3021 | done: |
3022 | Py_XDECREF(reason_str); |
3023 | Py_XDECREF(encoding_str); |
3024 | return result; |
3025 | } |
3026 | |
3027 | static PyTypeObject _PyExc_UnicodeDecodeError = { |
3028 | PyVarObject_HEAD_INIT(NULL, 0) |
3029 | "UnicodeDecodeError", |
3030 | sizeof(PyUnicodeErrorObject), 0, |
3031 | (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
3032 | (reprfunc)UnicodeDecodeError_str, 0, 0, 0, |
3033 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, |
3034 | PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse, |
3035 | (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, |
3036 | 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), |
3037 | (initproc)UnicodeDecodeError_init, 0, BaseException_new, |
3038 | }; |
3039 | PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError; |
3040 | |
3041 | PyObject * |
3042 | PyUnicodeDecodeError_Create( |
3043 | const char *encoding, const char *object, Py_ssize_t length, |
3044 | Py_ssize_t start, Py_ssize_t end, const char *reason) |
3045 | { |
3046 | return PyObject_CallFunction(PyExc_UnicodeDecodeError, "sy#nns", |
3047 | encoding, object, length, start, end, reason); |
3048 | } |
3049 | |
3050 | |
3051 | /* |
3052 | * UnicodeTranslateError extends UnicodeError |
3053 | */ |
3054 | |
3055 | static int |
3056 | UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args, |
3057 | PyObject *kwds) |
3058 | { |
3059 | if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) Branch (3059:9): [True: 0, False: 144]
|
3060 | return -1; |
3061 | |
3062 | Py_CLEAR(self->object); |
3063 | Py_CLEAR(self->reason); |
3064 | |
3065 | if (!PyArg_ParseTuple(args, "UnnU", Branch (3065:9): [True: 111, False: 33]
|
3066 | &self->object, |
3067 | &self->start, &self->end, &self->reason)) { |
3068 | self->object = self->reason = NULL; |
3069 | return -1; |
3070 | } |
3071 | |
3072 | Py_INCREF(self->object); |
3073 | Py_INCREF(self->reason); |
3074 | |
3075 | return 0; |
3076 | } |
3077 | |
3078 | |
3079 | static PyObject * |
3080 | UnicodeTranslateError_str(PyObject *self) |
3081 | { |
3082 | PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self; |
3083 | PyObject *result = NULL; |
3084 | PyObject *reason_str = NULL; |
3085 | |
3086 | if (!uself->object) Branch (3086:9): [True: 1, False: 10]
|
3087 | /* Not properly initialized. */ |
3088 | return PyUnicode_FromString(""); |
3089 | |
3090 | /* Get reason as a string, which it might not be if it's been |
3091 | modified after we were constructed. */ |
3092 | reason_str = PyObject_Str(uself->reason); |
3093 | if (reason_str == NULL) Branch (3093:9): [True: 0, False: 10]
|
3094 | goto done; |
3095 | |
3096 | if (uself->start < PyUnicode_GET_LENGTH(uself->object) && uself->end == uself->start+19 ) { Branch (3096:9): [True: 9, False: 1]
Branch (3096:63): [True: 6, False: 3]
|
3097 | Py_UCS4 badchar = PyUnicode_ReadChar(uself->object, uself->start); |
3098 | const char *fmt; |
3099 | if (badchar <= 0xff) Branch (3099:13): [True: 2, False: 4]
|
3100 | fmt = "can't translate character '\\x%02x' in position %zd: %U"; |
3101 | else if (badchar <= 0xffff) Branch (3101:18): [True: 3, False: 1]
|
3102 | fmt = "can't translate character '\\u%04x' in position %zd: %U"; |
3103 | else |
3104 | fmt = "can't translate character '\\U%08x' in position %zd: %U"; |
3105 | result = PyUnicode_FromFormat( |
3106 | fmt, |
3107 | (int)badchar, |
3108 | uself->start, |
3109 | reason_str |
3110 | ); |
3111 | } else { |
3112 | result = PyUnicode_FromFormat( |
3113 | "can't translate characters in position %zd-%zd: %U", |
3114 | uself->start, |
3115 | uself->end-1, |
3116 | reason_str |
3117 | ); |
3118 | } |
3119 | done: |
3120 | Py_XDECREF(reason_str); |
3121 | return result; |
3122 | } |
3123 | |
3124 | static PyTypeObject _PyExc_UnicodeTranslateError = { |
3125 | PyVarObject_HEAD_INIT(NULL, 0) |
3126 | "UnicodeTranslateError", |
3127 | sizeof(PyUnicodeErrorObject), 0, |
3128 | (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
3129 | (reprfunc)UnicodeTranslateError_str, 0, 0, 0, |
3130 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, |
3131 | PyDoc_STR("Unicode translation error."), (traverseproc)UnicodeError_traverse, |
3132 | (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, |
3133 | 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), |
3134 | (initproc)UnicodeTranslateError_init, 0, BaseException_new, |
3135 | }; |
3136 | PyObject *PyExc_UnicodeTranslateError = (PyObject *)&_PyExc_UnicodeTranslateError; |
3137 | |
3138 | PyObject * |
3139 | _PyUnicodeTranslateError_Create( |
3140 | PyObject *object, |
3141 | Py_ssize_t start, Py_ssize_t end, const char *reason) |
3142 | { |
3143 | return PyObject_CallFunction(PyExc_UnicodeTranslateError, "Onns", |
3144 | object, start, end, reason); |
3145 | } |
3146 | |
3147 | /* |
3148 | * AssertionError extends Exception |
3149 | */ |
3150 | SimpleExtendsException(PyExc_Exception, AssertionError, |
3151 | "Assertion failed."); |
3152 | |
3153 | |
3154 | /* |
3155 | * ArithmeticError extends Exception |
3156 | */ |
3157 | SimpleExtendsException(PyExc_Exception, ArithmeticError, |
3158 | "Base class for arithmetic errors."); |
3159 | |
3160 | |
3161 | /* |
3162 | * FloatingPointError extends ArithmeticError |
3163 | */ |
3164 | SimpleExtendsException(PyExc_ArithmeticError, FloatingPointError, |
3165 | "Floating point operation failed."); |
3166 | |
3167 | |
3168 | /* |
3169 | * OverflowError extends ArithmeticError |
3170 | */ |
3171 | SimpleExtendsException(PyExc_ArithmeticError, OverflowError, |
3172 | "Result too large to be represented."); |
3173 | |
3174 | |
3175 | /* |
3176 | * ZeroDivisionError extends ArithmeticError |
3177 | */ |
3178 | SimpleExtendsException(PyExc_ArithmeticError, ZeroDivisionError, |
3179 | "Second argument to a division or modulo operation was zero."); |
3180 | |
3181 | |
3182 | /* |
3183 | * SystemError extends Exception |
3184 | */ |
3185 | SimpleExtendsException(PyExc_Exception, SystemError, |
3186 | "Internal error in the Python interpreter.\n" |
3187 | "\n" |
3188 | "Please report this to the Python maintainer, along with the traceback,\n" |
3189 | "the Python version, and the hardware/OS platform and version."); |
3190 | |
3191 | |
3192 | /* |
3193 | * ReferenceError extends Exception |
3194 | */ |
3195 | SimpleExtendsException(PyExc_Exception, ReferenceError, |
3196 | "Weak ref proxy used after referent went away."); |
3197 | |
3198 | |
3199 | /* |
3200 | * MemoryError extends Exception |
3201 | */ |
3202 | |
3203 | #define MEMERRORS_SAVE 16 |
3204 | |
3205 | static PyObject * |
3206 | MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
3207 | { |
3208 | PyBaseExceptionObject *self; |
3209 | |
3210 | /* If this is a subclass of MemoryError, don't use the freelist |
3211 | * and just return a fresh object */ |
3212 | if (type != (PyTypeObject *) PyExc_MemoryError) { Branch (3212:9): [True: 1, False: 1.78k]
|
3213 | return BaseException_new(type, args, kwds); |
3214 | } |
3215 | |
3216 | struct _Py_exc_state *state = get_exc_state(); |
3217 | if (state->memerrors_freelist == NULL) { Branch (3217:9): [True: 1.71k, False: 69]
|
3218 | return BaseException_new(type, args, kwds); |
3219 | } |
3220 | |
3221 | /* Fetch object from freelist and revive it */ |
3222 | self = state->memerrors_freelist; |
3223 | self->args = PyTuple_New(0); |
3224 | /* This shouldn't happen since the empty tuple is persistent */ |
3225 | if (self->args == NULL) { Branch (3225:9): [True: 0, False: 69]
|
3226 | return NULL; |
3227 | } |
3228 | |
3229 | state->memerrors_freelist = (PyBaseExceptionObject *) self->dict; |
3230 | state->memerrors_numfree--; |
3231 | self->dict = NULL; |
3232 | _Py_NewReference((PyObject *)self); |
3233 | _PyObject_GC_TRACK(self); |
3234 | return (PyObject *)self; |
3235 | } |
3236 | |
3237 | static void |
3238 | MemoryError_dealloc(PyBaseExceptionObject *self) |
3239 | { |
3240 | BaseException_clear(self); |
3241 | |
3242 | /* If this is a subclass of MemoryError, we don't need to |
3243 | * do anything in the free-list*/ |
3244 | if (!Py_IS_TYPE(self, (PyTypeObject *) PyExc_MemoryError)) { Branch (3244:9): [True: 1, False: 1.78k]
|
3245 | Py_TYPE(self)->tp_free((PyObject *)self); |
3246 | return; |
3247 | } |
3248 | |
3249 | _PyObject_GC_UNTRACK(self); |
3250 | |
3251 | struct _Py_exc_state *state = get_exc_state(); |
3252 | if (state->memerrors_numfree >= MEMERRORS_SAVE) { Branch (3252:9): [True: 3, False: 1.78k]
|
3253 | Py_TYPE(self)->tp_free((PyObject *)self); |
3254 | } |
3255 | else { |
3256 | self->dict = (PyObject *) state->memerrors_freelist; |
3257 | state->memerrors_freelist = self; |
3258 | state->memerrors_numfree++; |
3259 | } |
3260 | } |
3261 | |
3262 | static int |
3263 | preallocate_memerrors(void) |
3264 | { |
3265 | /* We create enough MemoryErrors and then decref them, which will fill |
3266 | up the freelist. */ |
3267 | int i; |
3268 | PyObject *errors[MEMERRORS_SAVE]; |
3269 | for (i = 0; i < MEMERRORS_SAVE; i++1.71k ) { Branch (3269:17): [True: 1.71k, False: 107]
|
3270 | errors[i] = MemoryError_new((PyTypeObject *) PyExc_MemoryError, |
3271 | NULL, NULL); |
3272 | if (!errors[i]) { Branch (3272:13): [True: 0, False: 1.71k]
|
3273 | return -1; |
3274 | } |
3275 | } |
3276 | for (i = 0; 107 i < MEMERRORS_SAVE; i++1.71k ) { Branch (3276:17): [True: 1.71k, False: 107]
|
3277 | Py_DECREF(errors[i]); |
3278 | } |
3279 | return 0; |
3280 | } |
3281 | |
3282 | static void |
3283 | free_preallocated_memerrors(struct _Py_exc_state *state) |
3284 | { |
3285 | while (state->memerrors_freelist != NULL) { Branch (3285:12): [True: 1.64k, False: 272]
|
3286 | PyObject *self = (PyObject *) state->memerrors_freelist; |
3287 | state->memerrors_freelist = (PyBaseExceptionObject *)state->memerrors_freelist->dict; |
3288 | Py_TYPE(self)->tp_free((PyObject *)self); |
3289 | } |
3290 | } |
3291 | |
3292 | |
3293 | static PyTypeObject _PyExc_MemoryError = { |
3294 | PyVarObject_HEAD_INIT(NULL, 0) |
3295 | "MemoryError", |
3296 | sizeof(PyBaseExceptionObject), |
3297 | 0, (destructor)MemoryError_dealloc, 0, 0, 0, 0, 0, 0, 0, |
3298 | 0, 0, 0, 0, 0, 0, 0, |
3299 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, |
3300 | PyDoc_STR("Out of memory."), (traverseproc)BaseException_traverse, |
3301 | (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_PyExc_Exception, |
3302 | 0, 0, 0, offsetof(PyBaseExceptionObject, dict), |
3303 | (initproc)BaseException_init, 0, MemoryError_new |
3304 | }; |
3305 | PyObject *PyExc_MemoryError = (PyObject *) &_PyExc_MemoryError; |
3306 | |
3307 | |
3308 | /* |
3309 | * BufferError extends Exception |
3310 | */ |
3311 | SimpleExtendsException(PyExc_Exception, BufferError, "Buffer error."); |
3312 | |
3313 | |
3314 | /* Warning category docstrings */ |
3315 | |
3316 | /* |
3317 | * Warning extends Exception |
3318 | */ |
3319 | SimpleExtendsException(PyExc_Exception, Warning, |
3320 | "Base class for warning categories."); |
3321 | |
3322 | |
3323 | /* |
3324 | * UserWarning extends Warning |
3325 | */ |
3326 | SimpleExtendsException(PyExc_Warning, UserWarning, |
3327 | "Base class for warnings generated by user code."); |
3328 | |
3329 | |
3330 | /* |
3331 | * DeprecationWarning extends Warning |
3332 | */ |
3333 | SimpleExtendsException(PyExc_Warning, DeprecationWarning, |
3334 | "Base class for warnings about deprecated features."); |
3335 | |
3336 | |
3337 | /* |
3338 | * PendingDeprecationWarning extends Warning |
3339 | */ |
3340 | SimpleExtendsException(PyExc_Warning, PendingDeprecationWarning, |
3341 | "Base class for warnings about features which will be deprecated\n" |
3342 | "in the future."); |
3343 | |
3344 | |
3345 | /* |
3346 | * SyntaxWarning extends Warning |
3347 | */ |
3348 | SimpleExtendsException(PyExc_Warning, SyntaxWarning, |
3349 | "Base class for warnings about dubious syntax."); |
3350 | |
3351 | |
3352 | /* |
3353 | * RuntimeWarning extends Warning |
3354 | */ |
3355 | SimpleExtendsException(PyExc_Warning, RuntimeWarning, |
3356 | "Base class for warnings about dubious runtime behavior."); |
3357 | |
3358 | |
3359 | /* |
3360 | * FutureWarning extends Warning |
3361 | */ |
3362 | SimpleExtendsException(PyExc_Warning, FutureWarning, |
3363 | "Base class for warnings about constructs that will change semantically\n" |
3364 | "in the future."); |
3365 | |
3366 | |
3367 | /* |
3368 | * ImportWarning extends Warning |
3369 | */ |
3370 | SimpleExtendsException(PyExc_Warning, ImportWarning, |
3371 | "Base class for warnings about probable mistakes in module imports"); |
3372 | |
3373 | |
3374 | /* |
3375 | * UnicodeWarning extends Warning |
3376 | */ |
3377 | SimpleExtendsException(PyExc_Warning, UnicodeWarning, |
3378 | "Base class for warnings about Unicode related problems, mostly\n" |
3379 | "related to conversion problems."); |
3380 | |
3381 | |
3382 | /* |
3383 | * BytesWarning extends Warning |
3384 | */ |
3385 | SimpleExtendsException(PyExc_Warning, BytesWarning, |
3386 | "Base class for warnings about bytes and buffer related problems, mostly\n" |
3387 | "related to conversion from str or comparing to str."); |
3388 | |
3389 | |
3390 | /* |
3391 | * EncodingWarning extends Warning |
3392 | */ |
3393 | SimpleExtendsException(PyExc_Warning, EncodingWarning, |
3394 | "Base class for warnings about encodings."); |
3395 | |
3396 | |
3397 | /* |
3398 | * ResourceWarning extends Warning |
3399 | */ |
3400 | SimpleExtendsException(PyExc_Warning, ResourceWarning, |
3401 | "Base class for warnings about resource usage."); |
3402 | |
3403 | |
3404 | |
3405 | #ifdef MS_WINDOWS |
3406 | #include <winsock2.h> |
3407 | /* The following constants were added to errno.h in VS2010 but have |
3408 | preferred WSA equivalents. */ |
3409 | #undef EADDRINUSE |
3410 | #undef EADDRNOTAVAIL |
3411 | #undef EAFNOSUPPORT |
3412 | #undef EALREADY |
3413 | #undef ECONNABORTED |
3414 | #undef ECONNREFUSED |
3415 | #undef ECONNRESET |
3416 | #undef EDESTADDRREQ |
3417 | #undef EHOSTUNREACH |
3418 | #undef EINPROGRESS |
3419 | #undef EISCONN |
3420 | #undef ELOOP |
3421 | #undef EMSGSIZE |
3422 | #undef ENETDOWN |
3423 | #undef ENETRESET |
3424 | #undef ENETUNREACH |
3425 | #undef ENOBUFS |
3426 | #undef ENOPROTOOPT |
3427 | #undef ENOTCONN |
3428 | #undef ENOTSOCK |
3429 | #undef EOPNOTSUPP |
3430 | #undef EPROTONOSUPPORT |
3431 | #undef EPROTOTYPE |
3432 | #undef ETIMEDOUT |
3433 | #undef EWOULDBLOCK |
3434 | |
3435 | #if defined(WSAEALREADY) && !defined(EALREADY) |
3436 | #define EALREADY WSAEALREADY |
3437 | #endif |
3438 | #if defined(WSAECONNABORTED) && !defined(ECONNABORTED) |
3439 | #define ECONNABORTED WSAECONNABORTED |
3440 | #endif |
3441 | #if defined(WSAECONNREFUSED) && !defined(ECONNREFUSED) |
3442 | #define ECONNREFUSED WSAECONNREFUSED |
3443 | #endif |
3444 | #if defined(WSAECONNRESET) && !defined(ECONNRESET) |
3445 | #define ECONNRESET WSAECONNRESET |
3446 | #endif |
3447 | #if defined(WSAEINPROGRESS) && !defined(EINPROGRESS) |
3448 | #define EINPROGRESS WSAEINPROGRESS |
3449 | #endif |
3450 | #if defined(WSAESHUTDOWN) && !defined(ESHUTDOWN) |
3451 | #define ESHUTDOWN WSAESHUTDOWN |
3452 | #endif |
3453 | #if defined(WSAETIMEDOUT) && !defined(ETIMEDOUT) |
3454 | #define ETIMEDOUT WSAETIMEDOUT |
3455 | #endif |
3456 | #if defined(WSAEWOULDBLOCK) && !defined(EWOULDBLOCK) |
3457 | #define EWOULDBLOCK WSAEWOULDBLOCK |
3458 | #endif |
3459 | #endif /* MS_WINDOWS */ |
3460 | |
3461 | struct static_exception { |
3462 | PyTypeObject *exc; |
3463 | const char *name; |
3464 | }; |
3465 | |
3466 | static struct static_exception static_exceptions[] = { |
3467 | #define ITEM(NAME) {&_PyExc_##NAME, #NAME} |
3468 | // Level 1 |
3469 | ITEM(BaseException), |
3470 | |
3471 | // Level 2: BaseException subclasses |
3472 | ITEM(BaseExceptionGroup), |
3473 | ITEM(Exception), |
3474 | ITEM(GeneratorExit), |
3475 | ITEM(KeyboardInterrupt), |
3476 | ITEM(SystemExit), |
3477 | |
3478 | // Level 3: Exception(BaseException) subclasses |
3479 | ITEM(ArithmeticError), |
3480 | ITEM(AssertionError), |
3481 | ITEM(AttributeError), |
3482 | ITEM(BufferError), |
3483 | ITEM(EOFError), |
3484 | //ITEM(ExceptionGroup), |
3485 | ITEM(ImportError), |
3486 | ITEM(LookupError), |
3487 | ITEM(MemoryError), |
3488 | ITEM(NameError), |
3489 | ITEM(OSError), |
3490 | ITEM(ReferenceError), |
3491 | ITEM(RuntimeError), |
3492 | ITEM(StopAsyncIteration), |
3493 | ITEM(StopIteration), |
3494 | ITEM(SyntaxError), |
3495 | ITEM(SystemError), |
3496 | ITEM(TypeError), |
3497 | ITEM(ValueError), |
3498 | ITEM(Warning), |
3499 | |
3500 | // Level 4: ArithmeticError(Exception) subclasses |
3501 | ITEM(FloatingPointError), |
3502 | ITEM(OverflowError), |
3503 | ITEM(ZeroDivisionError), |
3504 | |
3505 | // Level 4: Warning(Exception) subclasses |
3506 | ITEM(BytesWarning), |
3507 | ITEM(DeprecationWarning), |
3508 | ITEM(EncodingWarning), |
3509 | ITEM(FutureWarning), |
3510 | ITEM(ImportWarning), |
3511 | ITEM(PendingDeprecationWarning), |
3512 | ITEM(ResourceWarning), |
3513 | ITEM(RuntimeWarning), |
3514 | ITEM(SyntaxWarning), |
3515 | ITEM(UnicodeWarning), |
3516 | ITEM(UserWarning), |
3517 | |
3518 | // Level 4: OSError(Exception) subclasses |
3519 | ITEM(BlockingIOError), |
3520 | ITEM(ChildProcessError), |
3521 | ITEM(ConnectionError), |
3522 | ITEM(FileExistsError), |
3523 | ITEM(FileNotFoundError), |
3524 | ITEM(InterruptedError), |
3525 | ITEM(IsADirectoryError), |
3526 | ITEM(NotADirectoryError), |
3527 | ITEM(PermissionError), |
3528 | ITEM(ProcessLookupError), |
3529 | ITEM(TimeoutError), |
3530 | |
3531 | // Level 4: Other subclasses |
3532 | ITEM(IndentationError), // base: SyntaxError(Exception) |
3533 | ITEM(IndexError), // base: LookupError(Exception) |
3534 | ITEM(KeyError), // base: LookupError(Exception) |
3535 | ITEM(ModuleNotFoundError), // base: ImportError(Exception) |
3536 | ITEM(NotImplementedError), // base: RuntimeError(Exception) |
3537 | ITEM(RecursionError), // base: RuntimeError(Exception) |
3538 | ITEM(UnboundLocalError), // base: NameError(Exception) |
3539 | ITEM(UnicodeError), // base: ValueError(Exception) |
3540 | |
3541 | // Level 5: ConnectionError(OSError) subclasses |
3542 | ITEM(BrokenPipeError), |
3543 | ITEM(ConnectionAbortedError), |
3544 | ITEM(ConnectionRefusedError), |
3545 | ITEM(ConnectionResetError), |
3546 | |
3547 | // Level 5: IndentationError(SyntaxError) subclasses |
3548 | ITEM(TabError), // base: IndentationError |
3549 | |
3550 | // Level 5: UnicodeError(ValueError) subclasses |
3551 | ITEM(UnicodeDecodeError), |
3552 | ITEM(UnicodeEncodeError), |
3553 | ITEM(UnicodeTranslateError), |
3554 | #undef ITEM |
3555 | }; |
3556 | |
3557 | |
3558 | int |
3559 | _PyExc_InitTypes(PyInterpreterState *interp) |
3560 | { |
3561 | if (!_Py_IsMainInterpreter(interp)) { Branch (3561:9): [True: 171, False: 107]
|
3562 | return 0; |
3563 | } |
3564 | |
3565 | for (size_t i=0; 107 i < Py_ARRAY_LENGTH(static_exceptions); i++7.06k ) { Branch (3565:22): [True: 7.06k, False: 107]
|
3566 | PyTypeObject *exc = static_exceptions[i].exc; |
3567 | |
3568 | if (PyType_Ready(exc) < 0) { Branch (3568:13): [True: 0, False: 7.06k]
|
3569 | return -1; |
3570 | } |
3571 | } |
3572 | return 0; |
3573 | } |
3574 | |
3575 | |
3576 | static void |
3577 | _PyExc_FiniTypes(PyInterpreterState *interp) |
3578 | { |
3579 | if (!_Py_IsMainInterpreter(interp)) { Branch (3579:9): [True: 169, False: 103]
|
3580 | return; |
3581 | } |
3582 | |
3583 | for (Py_ssize_t i=103 Py_ARRAY_LENGTH103 (static_exceptions) - 1; i >= 0; i--6.79k ) { Branch (3583:63): [True: 6.79k, False: 103]
|
3584 | PyTypeObject *exc = static_exceptions[i].exc; |
3585 | _PyStaticType_Dealloc(exc); |
3586 | } |
3587 | } |
3588 | |
3589 | |
3590 | PyStatus |
3591 | _PyExc_InitGlobalObjects(PyInterpreterState *interp) |
3592 | { |
3593 | if (!_Py_IsMainInterpreter(interp)) { Branch (3593:9): [True: 171, False: 107]
|
3594 | return _PyStatus_OK(); |
3595 | } |
3596 | |
3597 | if (preallocate_memerrors() < 0) { Branch (3597:9): [True: 0, False: 107]
|
3598 | return _PyStatus_NO_MEMORY(); |
3599 | } |
3600 | return _PyStatus_OK(); |
3601 | } |
3602 | |
3603 | PyStatus |
3604 | _PyExc_InitState(PyInterpreterState *interp) |
3605 | { |
3606 | struct _Py_exc_state *state = &interp->exc_state; |
3607 | |
3608 | #define ADD_ERRNO(TYPE, CODE) \ |
3609 | do { \ |
3610 | PyObject *_code = PyLong_FromLong(CODE); \ |
3611 | assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \ |
3612 | if (!_code || PyDict_SetItem(state->errnomap, _code, PyExc_ ## TYPE)) { \ |
3613 | Py_XDECREF(_code); \ |
3614 | return _PyStatus_ERR("errmap insertion problem."); \ |
3615 | } \ |
3616 | Py_DECREF(_code); \ |
3617 | } while (0) |
3618 | |
3619 | /* Add exceptions to errnomap */ |
3620 | assert(state->errnomap == NULL); |
3621 | state->errnomap = PyDict_New(); |
3622 | if (!state->errnomap) { Branch (3622:9): [True: 0, False: 278]
|
3623 | return _PyStatus_NO_MEMORY(); |
3624 | } |
3625 | |
3626 | ADD_ERRNO(BlockingIOError, EAGAIN); |
3627 | ADD_ERRNO(BlockingIOError, EALREADY); |
3628 | ADD_ERRNO(BlockingIOError, EINPROGRESS); |
3629 | ADD_ERRNO(BlockingIOError, EWOULDBLOCK); |
3630 | ADD_ERRNO(BrokenPipeError, EPIPE); |
3631 | #ifdef ESHUTDOWN |
3632 | ADD_ERRNO(BrokenPipeError, ESHUTDOWN); |
3633 | #endif |
3634 | ADD_ERRNO(ChildProcessError, ECHILD); |
3635 | ADD_ERRNO(ConnectionAbortedError, ECONNABORTED); |
3636 | ADD_ERRNO(ConnectionRefusedError, ECONNREFUSED); |
3637 | ADD_ERRNO(ConnectionResetError, ECONNRESET); |
3638 | ADD_ERRNO(FileExistsError, EEXIST); |
3639 | ADD_ERRNO(FileNotFoundError, ENOENT); |
3640 | ADD_ERRNO(IsADirectoryError, EISDIR); |
3641 | ADD_ERRNO(NotADirectoryError, ENOTDIR); |
3642 | ADD_ERRNO(InterruptedError, EINTR); |
3643 | ADD_ERRNO(PermissionError, EACCES); |
3644 | ADD_ERRNO(PermissionError, EPERM); |
3645 | ADD_ERRNO(ProcessLookupError, ESRCH); |
3646 | ADD_ERRNO(TimeoutError, ETIMEDOUT); |
3647 | |
3648 | return _PyStatus_OK(); |
3649 | |
3650 | #undef ADD_ERRNO |
3651 | } |
3652 | |
3653 | |
3654 | /* Add exception types to the builtins module */ |
3655 | int |
3656 | _PyBuiltins_AddExceptions(PyObject *bltinmod) |
3657 | { |
3658 | PyObject *mod_dict = PyModule_GetDict(bltinmod); |
3659 | if (mod_dict == NULL) { Branch (3659:9): [True: 0, False: 278]
|
3660 | return -1; |
3661 | } |
3662 | |
3663 | for (size_t i=0; 278 i < Py_ARRAY_LENGTH(static_exceptions); i++18.3k ) { Branch (3663:22): [True: 18.3k, False: 278]
|
3664 | struct static_exception item = static_exceptions[i]; |
3665 | |
3666 | if (PyDict_SetItemString(mod_dict, item.name, (PyObject*)item.exc)) { Branch (3666:13): [True: 0, False: 18.3k]
|
3667 | return -1; |
3668 | } |
3669 | } |
3670 | |
3671 | PyObject *PyExc_ExceptionGroup = create_exception_group_class(); |
3672 | if (!PyExc_ExceptionGroup) { Branch (3672:9): [True: 0, False: 278]
|
3673 | return -1; |
3674 | } |
3675 | if (PyDict_SetItemString(mod_dict, "ExceptionGroup", PyExc_ExceptionGroup)) { Branch (3675:9): [True: 0, False: 278]
|
3676 | return -1; |
3677 | } |
3678 | |
3679 | #define INIT_ALIAS(NAME, TYPE) \ |
3680 | do { \ |
3681 | PyExc_ ## NAME = PyExc_ ## TYPE; \ |
3682 | if (PyDict_SetItemString(mod_dict, # NAME, PyExc_ ## TYPE)) { \ |
3683 | return -1; \ |
3684 | } \ |
3685 | } while (0) |
3686 | |
3687 | INIT_ALIAS(EnvironmentError, OSError); |
3688 | INIT_ALIAS(IOError, OSError); |
3689 | #ifdef MS_WINDOWS |
3690 | INIT_ALIAS(WindowsError, OSError); |
3691 | #endif |
3692 | |
3693 | #undef INIT_ALIAS |
3694 | |
3695 | return 0; |
3696 | } |
3697 | |
3698 | void |
3699 | _PyExc_ClearExceptionGroupType(PyInterpreterState *interp) |
3700 | { |
3701 | struct _Py_exc_state *state = &interp->exc_state; |
3702 | Py_CLEAR(state->PyExc_ExceptionGroup); |
3703 | } |
3704 | |
3705 | void |
3706 | _PyExc_Fini(PyInterpreterState *interp) |
3707 | { |
3708 | struct _Py_exc_state *state = &interp->exc_state; |
3709 | free_preallocated_memerrors(state); |
3710 | Py_CLEAR(state->errnomap); |
3711 | |
3712 | _PyExc_FiniTypes(interp); |
3713 | } |
3714 | |
3715 | /* Helper to do the equivalent of "raise X from Y" in C, but always using |
3716 | * the current exception rather than passing one in. |
3717 | * |
3718 | * We currently limit this to *only* exceptions that use the BaseException |
3719 | * tp_init and tp_new methods, since we can be reasonably sure we can wrap |
3720 | * those correctly without losing data and without losing backwards |
3721 | * compatibility. |
3722 | * |
3723 | * We also aim to rule out *all* exceptions that might be storing additional |
3724 | * state, whether by having a size difference relative to BaseException, |
3725 | * additional arguments passed in during construction or by having a |
3726 | * non-empty instance dict. |
3727 | * |
3728 | * We need to be very careful with what we wrap, since changing types to |
3729 | * a broader exception type would be backwards incompatible for |
3730 | * existing codecs, and with different init or new method implementations |
3731 | * may either not support instantiation with PyErr_Format or lose |
3732 | * information when instantiated that way. |
3733 | * |
3734 | * XXX (ncoghlan): This could be made more comprehensive by exploiting the |
3735 | * fact that exceptions are expected to support pickling. If more builtin |
3736 | * exceptions (e.g. AttributeError) start to be converted to rich |
3737 | * exceptions with additional attributes, that's probably a better approach |
3738 | * to pursue over adding special cases for particular stateful subclasses. |
3739 | * |
3740 | * Returns a borrowed reference to the new exception (if any), NULL if the |
3741 | * existing exception was left in place. |
3742 | */ |
3743 | PyObject * |
3744 | _PyErr_TrySetFromCause(const char *format, ...) |
3745 | { |
3746 | PyObject* msg_prefix; |
3747 | PyObject *exc, *val, *tb; |
3748 | PyTypeObject *caught_type; |
3749 | PyObject *instance_args; |
3750 | Py_ssize_t num_args, caught_type_size, base_exc_size; |
3751 | PyObject *new_exc, *new_val, *new_tb; |
3752 | va_list vargs; |
3753 | int same_basic_size; |
3754 | |
3755 | PyErr_Fetch(&exc, &val, &tb); |
3756 | caught_type = (PyTypeObject *)exc; |
3757 | /* Ensure type info indicates no extra state is stored at the C level |
3758 | * and that the type can be reinstantiated using PyErr_Format |
3759 | */ |
3760 | caught_type_size = caught_type->tp_basicsize; |
3761 | base_exc_size = _PyExc_BaseException.tp_basicsize; |
3762 | same_basic_size = ( |
3763 | caught_type_size == base_exc_size || Branch (3763:9): [True: 75, False: 66]
|
3764 | (66 _PyType_SUPPORTS_WEAKREFS(caught_type)66 && Branch (3764:10): [True: 14, False: 52]
|
3765 | (caught_type_size == base_exc_size + (Py_ssize_t)sizeof(PyObject *))14 Branch (3765:13): [True: 14, False: 0]
|
3766 | ) |
3767 | ); |
3768 | if (caught_type->tp_init != (initproc)BaseException_init || Branch (3768:9): [True: 56, False: 85]
|
3769 | caught_type->tp_new != BaseException_new85 || Branch (3769:9): [True: 4, False: 81]
|
3770 | !same_basic_size81 || Branch (3770:9): [True: 0, False: 81]
|
3771 | caught_type->tp_itemsize != _PyExc_BaseException.tp_itemsize81 ) { Branch (3771:9): [True: 0, False: 81]
|
3772 | /* We can't be sure we can wrap this safely, since it may contain |
3773 | * more state than just the exception type. Accordingly, we just |
3774 | * leave it alone. |
3775 | */ |
3776 | PyErr_Restore(exc, val, tb); |
3777 | return NULL; |
3778 | } |
3779 | |
3780 | /* Check the args are empty or contain a single string */ |
3781 | PyErr_NormalizeException(&exc, &val, &tb); |
3782 | instance_args = ((PyBaseExceptionObject *)val)->args; |
3783 | num_args = PyTuple_GET_SIZE(instance_args); |
3784 | if (num_args > 1 || Branch (3784:9): [True: 4, False: 77]
|
3785 | (77 num_args == 177 && Branch (3785:10): [True: 73, False: 4]
|
3786 | !73 PyUnicode_CheckExact73 (PyTuple_GET_ITEM(instance_args, 0)))) { Branch (3786:10): [True: 4, False: 69]
|
3787 | /* More than 1 arg, or the one arg we do have isn't a string |
3788 | */ |
3789 | PyErr_Restore(exc, val, tb); |
3790 | return NULL; |
3791 | } |
3792 | |
3793 | /* Ensure the instance dict is also empty */ |
3794 | if (!_PyObject_IsInstanceDictEmpty(val)) { Branch (3794:9): [True: 4, False: 69]
|
3795 | /* While we could potentially copy a non-empty instance dictionary |
3796 | * to the replacement exception, for now we take the more |
3797 | * conservative path of leaving exceptions with attributes set |
3798 | * alone. |
3799 | */ |
3800 | PyErr_Restore(exc, val, tb); |
3801 | return NULL; |
3802 | } |
3803 | |
3804 | /* For exceptions that we can wrap safely, we chain the original |
3805 | * exception to a new one of the exact same type with an |
3806 | * error message that mentions the additional details and the |
3807 | * original exception. |
3808 | * |
3809 | * It would be nice to wrap OSError and various other exception |
3810 | * types as well, but that's quite a bit trickier due to the extra |
3811 | * state potentially stored on OSError instances. |
3812 | */ |
3813 | /* Ensure the traceback is set correctly on the existing exception */ |
3814 | if (tb != NULL) { Branch (3814:9): [True: 62, False: 7]
|
3815 | PyException_SetTraceback(val, tb); |
3816 | Py_DECREF(tb); |
3817 | } |
3818 | |
3819 | va_start(vargs, format); |
3820 | msg_prefix = PyUnicode_FromFormatV(format, vargs); |
3821 | va_end(vargs); |
3822 | if (msg_prefix == NULL) { Branch (3822:9): [True: 0, False: 69]
|
3823 | Py_DECREF(exc); |
3824 | Py_DECREF(val); |
3825 | return NULL; |
3826 | } |
3827 | |
3828 | PyErr_Format(exc, "%U (%s: %S)", |
3829 | msg_prefix, Py_TYPE(val)->tp_name, val); |
3830 | Py_DECREF(exc); |
3831 | Py_DECREF(msg_prefix); |
3832 | PyErr_Fetch(&new_exc, &new_val, &new_tb); |
3833 | PyErr_NormalizeException(&new_exc, &new_val, &new_tb); |
3834 | PyException_SetCause(new_val, val); |
3835 | PyErr_Restore(new_exc, new_val, new_tb); |
3836 | return new_val; |
3837 | } |