Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 10b24e8

Browse files
committed
Merged revisions 67688 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r67688 | amaury.forgeotdarc | 2008-12-11 00:22:49 +0100 (jeu., 11 déc. 2008) | 6 lines #4559: When a context manager's __exit__() method returns an object whose conversion to bool raises an exception, 'with' loses that exception. Reviewed by Jeffrey Yasskin. Already ported to 2.5, will port to 2.6 and 3.0 ........
1 parent ee76395 commit 10b24e8

3 files changed

Lines changed: 44 additions & 2 deletions

File tree

Lib/test/test_with.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,36 @@ def shouldThrow():
505505

506506
self.assertRaises(GeneratorExit, shouldThrow)
507507

508+
def testErrorsInBool(self):
509+
# issue4589: __exit__ return code may raise an exception
510+
# when looking at its truth value.
511+
512+
class cm(object):
513+
def __init__(self, bool_conversion):
514+
class Bool:
515+
def __bool__(self):
516+
return bool_conversion()
517+
self.exit_result = Bool()
518+
def __enter__(self):
519+
return 3
520+
def __exit__(self, a, b, c):
521+
return self.exit_result
522+
523+
def trueAsBool():
524+
with cm(lambda: True):
525+
self.fail("Should NOT see this")
526+
trueAsBool()
527+
528+
def falseAsBool():
529+
with cm(lambda: False):
530+
self.fail("Should raise")
531+
self.assertRaises(AssertionError, falseAsBool)
532+
533+
def failAsBool():
534+
with cm(lambda: 1//0):
535+
self.fail("Should NOT see this")
536+
self.assertRaises(ZeroDivisionError, failAsBool)
537+
508538

509539
class NonLocalFlowControlTestCase(unittest.TestCase):
510540

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 3.1 alpha 0
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #4597: Fixed exception handling when the __exit__ function of a
16+
context manager returns a value that cannot be converted to a bool.
17+
1518
- Issue #4445: Replace "sizeof(PyBytesObject)" with
1619
"offsetof(PyBytesObject, ob_sval) + 1" when allocating memory for
1720
bytes instances. On a typical machine this saves 3 bytes of memory

Python/ceval.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,15 +2189,24 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
21892189
Py_DECREF(exit_func);
21902190
if (x == NULL)
21912191
break; /* Go to error exit */
2192-
if (u != Py_None && PyObject_IsTrue(x)) {
2192+
2193+
if (u != Py_None)
2194+
err = PyObject_IsTrue(x);
2195+
else
2196+
err = 0;
2197+
Py_DECREF(x);
2198+
2199+
if (err < 0)
2200+
break; /* Go to error exit */
2201+
else if (err > 0) {
2202+
err = 0;
21932203
/* There was an exception and a True return */
21942204
STACKADJ(-2);
21952205
SET_TOP(PyLong_FromLong((long) WHY_SILENCED));
21962206
Py_DECREF(u);
21972207
Py_DECREF(v);
21982208
Py_DECREF(w);
21992209
}
2200-
Py_DECREF(x);
22012210
PREDICT(END_FINALLY);
22022211
break;
22032212
}

0 commit comments

Comments
 (0)