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 | |
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')
-rw-r--r-- | Python/ceval.c | 47 | ||||
-rw-r--r-- | Python/compile.c | 4 | ||||
-rw-r--r-- | Python/import.c | 1 |
3 files changed, 27 insertions, 25 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; } diff --git a/Python/compile.c b/Python/compile.c index c07b6d3..e3b3df8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1382,7 +1382,7 @@ opcode_stack_effect(int opcode, int oparg) case BREAK_LOOP: return 0; case WITH_CLEANUP: - return 3; + return -1; /* XXX Sometimes more */ case LOAD_LOCALS: return 1; case RETURN_VALUE: @@ -3472,8 +3472,6 @@ compiler_with(struct compiler *c, stmt_ty s) !compiler_nameop(c, tmpexit, Del)) return 0; ADDOP(c, WITH_CLEANUP); - ADDOP_I(c, CALL_FUNCTION, 3); - ADDOP(c, POP_TOP); /* Finally block ends. */ ADDOP(c, END_FINALLY); diff --git a/Python/import.c b/Python/import.c index f214ed5..73051a2 100644 --- a/Python/import.c +++ b/Python/import.c @@ -55,6 +55,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *); Python 2.5a0: 62071 Python 2.5a0: 62081 (ast-branch) Python 2.5a0: 62091 (with) + Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) . */ #define MAGIC (62092 | ((long)'\r'<<16) | ((long)'\n'<<24)) |