mirror of
https://github.com/python/cpython.git
synced 2025-07-29 14:15:07 +00:00
tabbify
This commit is contained in:
parent
bed26a3ce3
commit
8246968b12
3 changed files with 131 additions and 9 deletions
|
@ -21,6 +21,50 @@ class TracebackCases(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
raise ValueError, "call did not raise exception"
|
raise ValueError, "call did not raise exception"
|
||||||
|
|
||||||
|
def test_tb_next(self):
|
||||||
|
def f():
|
||||||
|
raise Exception
|
||||||
|
def g():
|
||||||
|
f()
|
||||||
|
try:
|
||||||
|
g()
|
||||||
|
except Exception:
|
||||||
|
tb = sys.exc_info()[2]
|
||||||
|
self.assertEqual(tb.tb_frame.f_code.co_name, "test_tb_next")
|
||||||
|
g_tb = tb.tb_next
|
||||||
|
self.assertEqual(g_tb.tb_frame.f_code.co_name, "g")
|
||||||
|
f_tb = g_tb.tb_next
|
||||||
|
self.assertEqual(f_tb.tb_frame.f_code.co_name, "f")
|
||||||
|
self.assertIsNone(f_tb.tb_next)
|
||||||
|
tb.tb_next = None
|
||||||
|
self.assertIsNone(tb.tb_next)
|
||||||
|
self.assertRaises(ValueError, setattr, f_tb, "tb_next", g_tb)
|
||||||
|
self.assertRaises(TypeError, setattr, tb, "tb_next", 4)
|
||||||
|
g_tb.tb_next = None
|
||||||
|
f_tb.tb_next = g_tb
|
||||||
|
self.assertIs(f_tb.tb_next, g_tb)
|
||||||
|
self.assertRaises(ValueError, setattr, f_tb, "tb_next", f_tb)
|
||||||
|
self.assertRaises(TypeError, delattr, tb, "tb_next")
|
||||||
|
|
||||||
|
def test_tb_frame(self):
|
||||||
|
def f():
|
||||||
|
x = 2
|
||||||
|
raise Exception
|
||||||
|
try:
|
||||||
|
f()
|
||||||
|
except Exception:
|
||||||
|
tb = sys.exc_info()[2]
|
||||||
|
self.assertIs(sys._getframe(), tb.tb_frame)
|
||||||
|
f_tb = tb.tb_next
|
||||||
|
self.assertEqual(f_tb.tb_frame.f_code.co_name, "f")
|
||||||
|
self.assertEqual(f_tb.tb_frame.f_locals["x"], 2)
|
||||||
|
f_tb.tb_frame = None
|
||||||
|
self.assertIsNone(f_tb.tb_frame)
|
||||||
|
self.assertRaises(TypeError, setattr, t_tb, "tb_frame", 4)
|
||||||
|
self.assertRaises(TypeError, delattr, t_tb, "tb_frame")
|
||||||
|
t_tb.tb_frame = sys._getframe()
|
||||||
|
self.assertIs(t_tb.tb_frame, tb.tb_frame)
|
||||||
|
|
||||||
def syntax_error_with_caret(self):
|
def syntax_error_with_caret(self):
|
||||||
compile("def fact(x):\n\treturn x!\n", "?", "exec")
|
compile("def fact(x):\n\treturn x!\n", "?", "exec")
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,7 @@ initpwd(void)
|
||||||
Py_INCREF((PyObject *) &StructPwdType);
|
Py_INCREF((PyObject *) &StructPwdType);
|
||||||
PyModule_AddObject(m, "struct_passwd", (PyObject *) &StructPwdType);
|
PyModule_AddObject(m, "struct_passwd", (PyObject *) &StructPwdType);
|
||||||
/* And for b/w compatibility (this was defined by mistake): */
|
/* And for b/w compatibility (this was defined by mistake): */
|
||||||
Py_INCREF((PyObject *) &StructPwdType);
|
Py_INCREF((PyObject *) &StructPwdType);
|
||||||
PyModule_AddObject(m, "struct_pwent", (PyObject *) &StructPwdType);
|
PyModule_AddObject(m, "struct_pwent", (PyObject *) &StructPwdType);
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
#define OFF(x) offsetof(PyTracebackObject, x)
|
#define OFF(x) offsetof(PyTracebackObject, x)
|
||||||
|
|
||||||
static PyMemberDef tb_memberlist[] = {
|
static PyMemberDef tb_memberlist[] = {
|
||||||
{"tb_next", T_OBJECT, OFF(tb_next), READONLY},
|
|
||||||
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
|
|
||||||
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
|
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
|
||||||
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
|
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
|
@ -45,6 +43,81 @@ tb_clear(PyTracebackObject *tb)
|
||||||
Py_CLEAR(tb->tb_frame);
|
Py_CLEAR(tb->tb_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
tb_get_next(PyTracebackObject *tb) {
|
||||||
|
if (tb->tb_next) {
|
||||||
|
Py_INCREF(tb->tb_next);
|
||||||
|
return (PyObject *)tb->tb_next;
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tb_set_next(PyTracebackObject *tb, PyObject *new, void *context) {
|
||||||
|
if (!new) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "can't delete tb_next");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (new == Py_None) {
|
||||||
|
new = NULL;
|
||||||
|
}
|
||||||
|
else if (PyTraceBack_Check(new)) {
|
||||||
|
/* Check for cycles in the traceback. */
|
||||||
|
PyTracebackObject *current = (PyTracebackObject *)new;
|
||||||
|
do {
|
||||||
|
if (tb == current) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "cycle in traceback");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while ((current = current->tb_next));
|
||||||
|
Py_INCREF(new);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"tb_next must be an traceback object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tb->tb_next);
|
||||||
|
tb->tb_next = (PyTracebackObject *)new;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
tb_get_frame(PyTracebackObject *tb) {
|
||||||
|
if (tb->tb_frame) {
|
||||||
|
Py_INCREF(tb->tb_frame);
|
||||||
|
return (PyObject *)tb->tb_frame;
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tb_set_frame(PyTracebackObject *tb, PyObject *new, void *context) {
|
||||||
|
if (!new) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"can't delete tb_frame attribute");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (new == Py_None) {
|
||||||
|
new = NULL;
|
||||||
|
}
|
||||||
|
else if (PyFrame_Check(new)) {
|
||||||
|
Py_INCREF(new);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"tb_frame must be a frame object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tb->tb_frame = (PyFrameObject *)new;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyGetSetDef tb_getset[] = {
|
||||||
|
{"tb_next", (getter)tb_get_next, (setter)tb_set_next, NULL},
|
||||||
|
{"tb_frame", (getter)tb_get_frame, (setter)tb_set_frame, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
PyTypeObject PyTraceBack_Type = {
|
PyTypeObject PyTraceBack_Type = {
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||||
"traceback",
|
"traceback",
|
||||||
|
@ -75,7 +148,7 @@ PyTypeObject PyTraceBack_Type = {
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
0, /* tp_methods */
|
0, /* tp_methods */
|
||||||
tb_memberlist, /* tp_members */
|
tb_memberlist, /* tp_members */
|
||||||
0, /* tp_getset */
|
tb_getset, /* tp_getset */
|
||||||
0, /* tp_base */
|
0, /* tp_base */
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
};
|
};
|
||||||
|
@ -245,11 +318,16 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
||||||
}
|
}
|
||||||
while (tb != NULL && err == 0) {
|
while (tb != NULL && err == 0) {
|
||||||
if (depth <= limit) {
|
if (depth <= limit) {
|
||||||
err = tb_displayline(f,
|
PyFrameObject *frame = tb->tb_frame;
|
||||||
PyString_AsString(
|
char *filename, *name;
|
||||||
tb->tb_frame->f_code->co_filename),
|
if (frame) {
|
||||||
tb->tb_lineno,
|
filename = PyString_AS_STRING(frame->f_code->co_filename);
|
||||||
PyString_AsString(tb->tb_frame->f_code->co_name));
|
name = PyString_AS_STRING(frame->f_code->co_name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filename = name = "unkown (no frame on traceback)";
|
||||||
|
}
|
||||||
|
err = tb_displayline(f, filename, tb->tb_lineno, name);
|
||||||
}
|
}
|
||||||
depth--;
|
depth--;
|
||||||
tb = tb->tb_next;
|
tb = tb->tb_next;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue