]> granicus.if.org Git - python/commitdiff
tabbify
authorBenjamin Peterson <benjamin@python.org>
Wed, 9 Sep 2009 11:40:54 +0000 (11:40 +0000)
committerBenjamin Peterson <benjamin@python.org>
Wed, 9 Sep 2009 11:40:54 +0000 (11:40 +0000)
Lib/test/test_traceback.py
Modules/pwdmodule.c
Python/traceback.c

index b29869ac8f8a24f4c85f46f0007995055294241f..d7dcbacaf681fca7f932eaf3f4a1e28bf9880323 100644 (file)
@@ -21,6 +21,50 @@ class TracebackCases(unittest.TestCase):
         else:
             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):
         compile("def fact(x):\n\treturn x!\n", "?", "exec")
 
index 2865dc6bf41fb2d8f480dfd292ad8c2559293f5b..d1ce39414995a061ab04ffb7592b3ac4e4a7959e 100644 (file)
@@ -194,7 +194,7 @@ initpwd(void)
        Py_INCREF((PyObject *) &StructPwdType);
        PyModule_AddObject(m, "struct_passwd", (PyObject *) &StructPwdType);
        /* 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);
        initialized = 1;
 }
index 1c26ba271abcf75268a34b5cad2b2a224de8df7d..b96ca47bc80de50d45df9e9fe2466727efcf15f9 100644 (file)
@@ -12,8 +12,6 @@
 #define OFF(x) offsetof(PyTracebackObject, x)
 
 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_lineno",   T_INT,          OFF(tb_lineno), READONLY},
        {NULL}  /* Sentinel */
@@ -45,6 +43,81 @@ tb_clear(PyTracebackObject *tb)
        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 = {
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
        "traceback",
@@ -75,7 +148,7 @@ PyTypeObject PyTraceBack_Type = {
        0,                                      /* tp_iternext */
        0,                                      /* tp_methods */
        tb_memberlist,                          /* tp_members */
-       0,                                      /* tp_getset */
+       tb_getset,                              /* tp_getset */
        0,                                      /* tp_base */
        0,                                      /* tp_dict */
 };
@@ -245,11 +318,16 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
        }
        while (tb != NULL && err == 0) {
                if (depth <= limit) {
-                       err = tb_displayline(f,
-                           PyString_AsString(
-                                   tb->tb_frame->f_code->co_filename),
-                           tb->tb_lineno,
-                           PyString_AsString(tb->tb_frame->f_code->co_name));
+                       PyFrameObject *frame = tb->tb_frame;
+                       char *filename, *name;
+                       if (frame) {
+                               filename = PyString_AS_STRING(frame->f_code->co_filename);
+                               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--;
                tb = tb->tb_next;