summaryrefslogtreecommitdiffstats
path: root/Lib
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 /Lib
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 'Lib')
-rw-r--r--Lib/compiler/pyassem.py2
-rw-r--r--Lib/compiler/pycodegen.py2
-rw-r--r--Lib/contextlib.py11
-rw-r--r--Lib/decimal.py2
-rw-r--r--Lib/test/test_with.py32
-rw-r--r--Lib/threading.py6
6 files changed, 28 insertions, 27 deletions
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 @@ class StackDepthTracker:
'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 @@ class CodeGenerator:
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 @@ class GeneratorContextManager(object):
else:
try:
self.gen.throw(type, value, traceback)
+ return True
except StopIteration:
- pass
+ return True
def contextmanager(func):
@@ -91,6 +92,7 @@ def nested(*contexts):
"""
exits = []
vars = []
+ exc = (None, None, None)
try:
try:
for context in contexts:
@@ -102,17 +104,14 @@ def nested(*contexts):
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 @@ class ContextManager(object):
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 @@ class Nested(object):
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 @@ class Nested(object):
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 AssignmentTargetTestCase(unittest.TestCase):
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 AssignmentTargetTestCase(unittest.TestCase):
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 @@ class _RLock(_Verbose):
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 @@ class _Condition(_Verbose):
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 @@ class _Semaphore(_Verbose):
def __exit__(self, t, v, tb):
self.release()
- if t is not None:
- raise t, v, tb
def BoundedSemaphore(*args, **kwargs):