From: <pj...@us...> - 2008-12-30 07:12:03
|
Revision: 5815 http://jython.svn.sourceforge.net/jython/?rev=5815&view=rev Author: pjenvey Date: 2008-12-30 07:11:59 +0000 (Tue, 30 Dec 2008) Log Message: ----------- o fix mishandling of tracebacks during re-raises. they're now special cased when PyException.isReRaise (analogous to CPython's why == WHY_RERAISE) is true o expose PyTraceback Modified Paths: -------------- trunk/jython/CoreExposed.includes trunk/jython/Lib/test/test_traceback_jy.py trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/PyException.java trunk/jython/src/org/python/core/PyTableCode.java trunk/jython/src/org/python/core/PyTraceback.java Modified: trunk/jython/CoreExposed.includes =================================================================== --- trunk/jython/CoreExposed.includes 2008-12-30 03:53:59 UTC (rev 5814) +++ trunk/jython/CoreExposed.includes 2008-12-30 07:11:59 UTC (rev 5815) @@ -34,6 +34,7 @@ org/python/core/PyStaticMethod.class org/python/core/PyString.class org/python/core/PySuper.class +org/python/core/PyTraceback.class org/python/core/PyTuple.class org/python/core/PyType.class org/python/core/PyUnicode.class Modified: trunk/jython/Lib/test/test_traceback_jy.py =================================================================== --- trunk/jython/Lib/test/test_traceback_jy.py 2008-12-30 03:53:59 UTC (rev 5814) +++ trunk/jython/Lib/test/test_traceback_jy.py 2008-12-30 07:11:59 UTC (rev 5815) @@ -24,18 +24,15 @@ try: EventQueue.invokeAndWait(PyRunnable()) except TypeError: - # XXX: - """ self.assertEqual(tb_info(), [('test_tb_across_threads', 'EventQueue.invokeAndWait(PyRunnable())'), ('run', "raise TypeError('this is only a test')")]) - """ else: self.fail('Expected TypeError') - def _test_reraise(self): + def test_reraise(self): def raiser(): raise Exception(), None, tb try: Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2008-12-30 03:53:59 UTC (rev 5814) +++ trunk/jython/src/org/python/core/Py.java 2008-12-30 07:11:59 UTC (rev 5815) @@ -1113,28 +1113,15 @@ /* Helpers to implement finally clauses */ public static void addTraceback(Throwable t, PyFrame frame) { - PyException e = Py.JavaError(t); - - //Add another traceback object to the exception if needed - if (e.traceback.tb_frame != frame && e.traceback.tb_frame.f_back != null) { - e.traceback = new PyTraceback(e.traceback); - } + Py.JavaError(t).tracebackHere(frame, true); } /* Helpers to implement except clauses */ public static PyException setException(Throwable t, PyFrame frame) { PyException pye = Py.JavaError(t); pye.normalize(); - - // attach catching frame - if (frame != null && pye.traceback.tb_frame != frame && pye.traceback.tb_frame.f_back != null) { - pye.traceback = new PyTraceback(pye.traceback); - } - - ThreadState ts = getThreadState(); - - ts.exception = pye; - + pye.tracebackHere(frame); + getThreadState().exception = pye; return pye; } Modified: trunk/jython/src/org/python/core/PyException.java =================================================================== --- trunk/jython/src/org/python/core/PyException.java 2008-12-30 03:53:59 UTC (rev 5814) +++ trunk/jython/src/org/python/core/PyException.java 2008-12-30 07:11:59 UTC (rev 5815) @@ -20,8 +20,15 @@ */ public PyObject value = Py.None; + /** The exception traceback object. */ public PyTraceback traceback; + /** + * Whether the exception was re-raised, such as when a traceback is specified to + * 'raise', or via a 'finally' block. + */ + private boolean isReRaise = false; + private boolean normalized = false; public PyException() { @@ -39,17 +46,9 @@ public PyException(PyObject type, PyObject value, PyTraceback traceback) { this.type = type; this.value = value; - if (traceback != null) { this.traceback = traceback; - } else { - PyFrame frame = Py.getFrame(); - if (frame != null) { - this.traceback = new PyTraceback(frame); - if (frame.tracefunc != null) { - frame.tracefunc = frame.tracefunc.traceException(frame, this); - } - } + isReRaise = true; } } @@ -133,6 +132,32 @@ } /** + * Register frame as having been visited in the traceback. + * + * @param here the current PyFrame + */ + public void tracebackHere(PyFrame here) { + tracebackHere(here, false); + } + + /** + * Register frame as having been visited in the traceback. + * + * @param here the current PyFrame + * @param isFinally whether caller is a Python finally block + */ + public void tracebackHere(PyFrame here, boolean isFinally) { + if (!isReRaise && here != null) { + // the frame is either inapplicable or already registered (from a finally) + // during a re-raise + traceback = new PyTraceback(traceback, here); + } + // finally blocks immediately tracebackHere: so they toggle isReRaise to skip the + // next tracebackHere hook + isReRaise = isFinally; + } + + /** * Logic for the raise statement * * @param type the first arg to raise, a type or an instance @@ -185,6 +210,7 @@ throw Py.TypeError("exceptions must be classes, instances, or strings (deprecated), " + "not " + type.getType().fastGetName()); } + return new PyException(type, value, (PyTraceback)traceback); } @@ -202,7 +228,7 @@ return false; } PyType type = ((PyType)obj); - if(type.isSubType((PyType)Py.BaseException)){ + if (type.isSubType(PyBaseException.TYPE)) { return true; } return type.getProxyType() != null && Throwable.class.isAssignableFrom(type.getProxyType()); Modified: trunk/jython/src/org/python/core/PyTableCode.java =================================================================== --- trunk/jython/src/org/python/core/PyTableCode.java 2008-12-30 03:53:59 UTC (rev 5814) +++ trunk/jython/src/org/python/core/PyTableCode.java 2008-12-30 07:11:59 UTC (rev 5815) @@ -198,37 +198,23 @@ try { ret = funcs.call_function(func_id, frame); } catch (Throwable t) { - //t.printStackTrace(); - //Convert exceptions that occured in Java code to PyExceptions - PyException e = Py.JavaError(t); + // Convert exceptions that occured in Java code to PyExceptions + PyException pye = Py.JavaError(t); + pye.tracebackHere(frame); - //Add another traceback object to the exception if needed - if (e.traceback.tb_frame != frame) { - PyTraceback tb; - // If f_back is null, we've jumped threads so use the current - // threadstate's frame. Bug #1533624 - if(e.traceback.tb_frame.f_back == null) { - tb = new PyTraceback(ts.frame); - } else { - tb = new PyTraceback(e.traceback.tb_frame.f_back); - } - tb.tb_next = e.traceback; - e.traceback = tb; - } - frame.f_lasti = -1; if (frame.tracefunc != null) { - frame.tracefunc.traceException(frame, e); + frame.tracefunc.traceException(frame, pye); } if (ts.profilefunc != null) { - ts.profilefunc.traceException(frame, e); + ts.profilefunc.traceException(frame, pye); } - //Rethrow the exception to the next stack frame + // Rethrow the exception to the next stack frame ts.exception = previous_exception; ts.frame = ts.frame.f_back; - throw e; + throw pye; } if (frame.tracefunc != null) { Modified: trunk/jython/src/org/python/core/PyTraceback.java =================================================================== --- trunk/jython/src/org/python/core/PyTraceback.java 2008-12-30 03:53:59 UTC (rev 5814) +++ trunk/jython/src/org/python/core/PyTraceback.java 2008-12-30 07:11:59 UTC (rev 5815) @@ -2,33 +2,32 @@ package org.python.core; import org.python.core.util.RelativeFile; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedType; /** * A python traceback object. */ -// XXX: isBaseType = false -public class PyTraceback extends PyObject -{ +@ExposedType(name = "traceback", isBaseType = false) +public class PyTraceback extends PyObject { + + public static final PyType TYPE = PyType.fromClass(PyTraceback.class); + + @ExposedGet public PyObject tb_next; + + @ExposedGet public PyFrame tb_frame; + + @ExposedGet public int tb_lineno; - public PyTraceback(PyFrame frame) { + public PyTraceback(PyTraceback next, PyFrame frame) { + tb_next = next; tb_frame = frame; - if (tb_frame != null) { - tb_lineno = tb_frame.getline(); - } - tb_next = Py.None; + tb_lineno = frame.getline(); } - public PyTraceback(PyTraceback next) { - tb_next = next; - if (next != null) { - tb_frame = next.tb_frame.f_back; - tb_lineno = tb_frame.getline(); - } - } - private String tracebackInfo() { if (tb_frame == null || tb_frame.f_code == null) { return String.format(" (no code object) at line %s\n", tb_lineno); @@ -103,7 +102,7 @@ public void dumpStack(StringBuilder buf) { buf.append(tracebackInfo()); - if (tb_next != Py.None && tb_next != this) { + if (tb_next != null && tb_next != this) { ((PyTraceback)tb_next).dumpStack(buf); } else if (tb_next == this) { buf.append("circularity detected!"+this+tb_next); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |