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.
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py
index b59661f..82ff396 100644
--- a/Lib/compiler/pyassem.py
+++ b/Lib/compiler/pyassem.py
@@ -779,7 +779,7 @@
         'SETUP_EXCEPT': 3,
         'SETUP_FINALLY': 3,
         'FOR_ITER': 1,
-        'WITH_CLEANUP': 3,
+        'WITH_CLEANUP': -1,
         }
     # use pattern match
     patterns = [
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index a1236de..2b3a24f 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -858,8 +858,6 @@
         self.nextBlock(final)
         self.setups.push((END_FINALLY, final))
         self.emit('WITH_CLEANUP')
-        self.emit('CALL_FUNCTION', 3)
-        self.emit('POP_TOP')
         self.emit('END_FINALLY')
         self.setups.pop()
         self.__with_count -= 1
diff --git a/Lib/contextlib.py b/Lib/contextlib.py
index 33c302d..0a5d608 100644
--- a/Lib/contextlib.py
+++ b/Lib/contextlib.py
@@ -30,8 +30,9 @@
         else:
             try:
                 self.gen.throw(type, value, traceback)
+                return True
             except StopIteration:
-                pass
+                return True
 
 
 def contextmanager(func):
@@ -91,6 +92,7 @@
     """
     exits = []
     vars = []
+    exc = (None, None, None)
     try:
         try:
             for context in contexts:
@@ -102,17 +104,14 @@
             yield vars
         except:
             exc = sys.exc_info()
-        else:
-            exc = (None, None, None)
     finally:
         while exits:
             exit = exits.pop()
             try:
-                exit(*exc)
+                if exit(*exc):
+                    exc = (None, None, None)
             except:
                 exc = sys.exc_info()
-            else:
-                exc = (None, None, None)
         if exc != (None, None, None):
             raise
 
diff --git a/Lib/decimal.py b/Lib/decimal.py
index 49f8115..967f101 100644
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -2196,8 +2196,6 @@
         return self.new_context
     def __exit__(self, t, v, tb):
         setcontext(self.saved_context)
-        if t is not None:
-            raise t, v, tb
 
 class Context(object):
     """Contains the context for a Decimal instance.
diff --git a/Lib/test/test_with.py b/Lib/test/test_with.py
index 36035e3..4854436 100644
--- a/Lib/test/test_with.py
+++ b/Lib/test/test_with.py
@@ -78,8 +78,8 @@
                 vars.append(mgr.__enter__())
                 self.entered.appendleft(mgr)
         except:
-            self.__exit__(*sys.exc_info())
-            raise
+            if not self.__exit__(*sys.exc_info()):
+                raise
         return vars
 
     def __exit__(self, *exc_info):
@@ -89,7 +89,8 @@
         ex = exc_info
         for mgr in self.entered:
             try:
-                mgr.__exit__(*ex)
+                if mgr.__exit__(*ex):
+                    ex = (None, None, None)
             except:
                 ex = sys.exc_info()
         self.entered = None
@@ -574,9 +575,7 @@
         class C:
             def __context__(self): return self
             def __enter__(self): return 1, 2, 3
-            def __exit__(self, t, v, tb):
-                if t is not None:
-                    raise t, v, tb
+            def __exit__(self, t, v, tb): pass
         targets = {1: [0, 1, 2]}
         with C() as (targets[1][0], targets[1][1], targets[1][2]):
             self.assertEqual(targets, {1: [1, 2, 3]})
@@ -594,17 +593,30 @@
 
 class ExitSwallowsExceptionTestCase(unittest.TestCase):
 
-    def testExitSwallowsException(self):
-        class AfricanOrEuropean:
+    def testExitTrueSwallowsException(self):
+        class AfricanSwallow:
             def __context__(self): return self
             def __enter__(self): pass
-            def __exit__(self, t, v, tb): pass
+            def __exit__(self, t, v, tb): return True
         try:
-            with AfricanOrEuropean():
+            with AfricanSwallow():
                 1/0
         except ZeroDivisionError:
             self.fail("ZeroDivisionError should have been swallowed")
 
+    def testExitFalseDoesntSwallowException(self):
+        class EuropeanSwallow:
+            def __context__(self): return self
+            def __enter__(self): pass
+            def __exit__(self, t, v, tb): return False
+        try:
+            with EuropeanSwallow():
+                1/0
+        except ZeroDivisionError:
+            pass
+        else:
+            self.fail("ZeroDivisionError should have been raised")
+
 
 def test_main():
     run_unittest(FailureTestCase, NonexceptionalTestCase,
diff --git a/Lib/threading.py b/Lib/threading.py
index 5b485d5..cc1adce 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -128,8 +128,6 @@
 
     def __exit__(self, t, v, tb):
         self.release()
-        if t is not None:
-            raise t, v, tb
 
     # Internal methods used by condition variables
 
@@ -190,8 +188,6 @@
 
     def __exit__(self, t, v, tb):
         self.release()
-        if t is not None:
-            raise t, v, tb
 
     def __repr__(self):
         return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters))
@@ -321,8 +317,6 @@
 
     def __exit__(self, t, v, tb):
         self.release()
-        if t is not None:
-            raise t, v, tb
 
 
 def BoundedSemaphore(*args, **kwargs):
diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c
index f15cacb..9a6c5d8 100644
--- a/Modules/threadmodule.c
+++ b/Modules/threadmodule.c
@@ -68,7 +68,7 @@
 
 PyDoc_STRVAR(acquire_doc,
 "acquire([wait]) -> None or bool\n\
-(PyThread_acquire_lock() is an obsolete synonym)\n\
+(acquire_lock() is an obsolete synonym)\n\
 \n\
 Lock the lock.  Without argument, this blocks if the lock is already\n\
 locked (even by the same thread), waiting for another thread to release\n\
@@ -94,7 +94,7 @@
 
 PyDoc_STRVAR(release_doc,
 "release()\n\
-(PyThread_release_lock() is an obsolete synonym)\n\
+(release_lock() is an obsolete synonym)\n\
 \n\
 Release the lock, allowing another thread that is blocked waiting for\n\
 the lock to acquire the lock.  The lock must be in the locked state,\n\
@@ -123,29 +123,6 @@
 	return (PyObject *)self;
 }
 
-PyDoc_STRVAR(lock_exit_doc,
-"__exit__(type, value, tb)\n\
-\n\
-Releases the lock; then re-raises the exception if type is not None.");
-
-static PyObject *
-lock_exit(lockobject *self, PyObject *args)
-{
-	PyObject *type, *value, *tb, *result;
-	if (!PyArg_ParseTuple(args, "OOO:__exit__", &type, &value, &tb))
-		return NULL;
-	result = lock_PyThread_release_lock(self);
-	if (result != NULL && type != Py_None) {
-		Py_DECREF(result);
-		result = NULL;
-		Py_INCREF(type);
-		Py_INCREF(value);
-		Py_INCREF(tb);
-		PyErr_Restore(type, value, tb);
-	}
-	return result;
-}
-
 static PyMethodDef lock_methods[] = {
 	{"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock, 
 	 METH_VARARGS, acquire_doc},
@@ -163,8 +140,8 @@
 	 METH_NOARGS, PyDoc_STR("__context__() -> self.")},
 	{"__enter__",    (PyCFunction)lock_PyThread_acquire_lock,
 	 METH_VARARGS, acquire_doc},
-	{"__exit__",    (PyCFunction)lock_exit,
-	 METH_VARARGS, lock_exit_doc},
+	{"__exit__",    (PyCFunction)lock_PyThread_release_lock,
+	 METH_VARARGS, release_doc},
 	{NULL,           NULL}		/* sentinel */
 };
 
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index b39a10f..57a9e9d 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -1617,24 +1617,6 @@
 	return (PyObject *)f;
 }
 
-static PyObject *
-file_exit(PyFileObject *f, PyObject *args)
-{
-	PyObject *type, *value, *tb, *result;
-	if (!PyArg_ParseTuple(args, "OOO:__exit__", &type, &value, &tb))
-		return NULL;
-	result = file_close(f);
-	if (result != NULL && type != Py_None) {
-		Py_DECREF(result);
-		result = NULL;
-		Py_INCREF(type);
-		Py_INCREF(value);
-		Py_INCREF(tb);
-		PyErr_Restore(type, value, tb);
-	}
-	return result;
-}
-
 PyDoc_STRVAR(readline_doc,
 "readline([size]) -> next line from the file, as a string.\n"
 "\n"
@@ -1725,13 +1707,6 @@
 PyDoc_STRVAR(enter_doc,
 	     "__enter__() -> self.");
 
-PyDoc_STRVAR(exit_doc,
-"__exit__(type, value, traceback).\n\
-\n\
-Closes the file; then re-raises the exception if type is not None.\n\
-If no exception is re-raised, the return value is the same as for close().\n\
-");
-
 static PyMethodDef file_methods[] = {
 	{"readline",  (PyCFunction)file_readline, METH_VARARGS, readline_doc},
 	{"read",      (PyCFunction)file_read,     METH_VARARGS, read_doc},
@@ -1751,7 +1726,7 @@
 	{"isatty",    (PyCFunction)file_isatty,   METH_NOARGS,  isatty_doc},
 	{"__context__", (PyCFunction)file_self,   METH_NOARGS,  context_doc},
 	{"__enter__", (PyCFunction)file_self,     METH_NOARGS,  enter_doc},
-	{"__exit__",  (PyCFunction)file_exit,     METH_VARARGS, exit_doc},
+	{"__exit__",  (PyCFunction)file_close,    METH_VARARGS, close_doc},
 	{NULL,	      NULL}		/* sentinel */
 };
 
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 @@
 			   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);
-				Py_INCREF(Py_None);
-				SET_SECOND(Py_None);
 			}
-			STACKADJ(3);
-			SET_THIRD(u);
-			SET_SECOND(v);
-			SET_TOP(w);
+			/* 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_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);
+			}
 			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 @@
 		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_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 @@
        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))