diff options
author | Guido van Rossum <guido@python.org> | 2006-03-10 02:28:35 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2006-03-10 02:28:35 (GMT) |
commit | f669436189dd44a841caa9ab1ad97a3f7662bf58 (patch) | |
tree | 1a717975d09d4867e8807710a36a6c2999afdb7e /Python/ceval.c | |
parent | 692cdbc5d648da5239b5caececc954960aa024e9 (diff) | |
download | cpython-f669436189dd44a841caa9ab1ad97a3f7662bf58.zip cpython-f669436189dd44a841caa9ab1ad97a3f7662bf58.tar.gz cpython-f669436189dd44a841caa9ab1ad97a3f7662bf58.tar.bz2 |
Um, I thought I'd already checked this in.
Anyway, this is the changes to the with-statement
so that __exit__ must return a true value in order
for a pending exception to be ignored.
The PEP (343) is already updated.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index e7fb875..de2b35b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2189,48 +2189,51 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw) Below that are 1-3 values indicating how/why we entered the finally clause: - SECOND = None - - (SECOND, THIRD) = (WHY_RETURN or WHY_CONTINUE), retval + - (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval - SECOND = WHY_*; no retval below it - (SECOND, THIRD, FOURTH) = exc_info() In the last case, we must call TOP(SECOND, THIRD, FOURTH) otherwise we must call TOP(None, None, None) - but we must preserve the stack entries below TOP. - The code here just sets the stack up for the call; - separate CALL_FUNCTION(3) and POP_TOP opcodes are - emitted by the compiler. In addition, if the stack represents an exception, - we "zap" this information; __exit__() should - re-raise the exception if it wants to, and if - __exit__() returns normally, END_FINALLY should - *not* re-raise the exception. (But non-local - gotos should still be resumed.) + *and* the function call returns a 'true' value, we + "zap" this information, to prevent END_FINALLY from + re-raising the exception. (But non-local gotos + should still be resumed.) */ x = TOP(); u = SECOND(); if (PyInt_Check(u) || u == Py_None) { u = v = w = Py_None; - Py_INCREF(u); - Py_INCREF(v); - Py_INCREF(w); } else { v = THIRD(); w = FOURTH(); - /* Zap the exception from the stack, - to fool END_FINALLY. */ - STACKADJ(-2); - SET_TOP(x); + } + /* XXX Not the fastest way to call it... */ + x = PyObject_CallFunctionObjArgs(x, u, v, w, NULL); + if (x == NULL) + break; /* Go to error exit */ + if (u != Py_None && PyObject_IsTrue(x)) { + /* There was an exception and a true return */ + Py_DECREF(x); + x = TOP(); /* Again */ + STACKADJ(-3); Py_INCREF(Py_None); - SET_SECOND(Py_None); + SET_TOP(Py_None); + Py_DECREF(x); + Py_DECREF(u); + Py_DECREF(v); + Py_DECREF(w); + } else { + /* Let END_FINALLY do its thing */ + Py_DECREF(x); + x = POP(); + Py_DECREF(x); } - STACKADJ(3); - SET_THIRD(u); - SET_SECOND(v); - SET_TOP(w); break; } |