summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2006-03-10 02:28:35 (GMT)
committerGuido van Rossum <guido@python.org>2006-03-10 02:28:35 (GMT)
commitf669436189dd44a841caa9ab1ad97a3f7662bf58 (patch)
tree1a717975d09d4867e8807710a36a6c2999afdb7e /Python
parent692cdbc5d648da5239b5caececc954960aa024e9 (diff)
downloadcpython-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.c47
-rw-r--r--Python/compile.c4
-rw-r--r--Python/import.c1
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))